summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/camera/AndroidCameraManagerImpl.java56
-rw-r--r--src/com/android/camera/BestpictureActivity.java7
-rwxr-xr-xsrc/com/android/camera/CameraActivity.java151
-rwxr-xr-xsrc/com/android/camera/CameraHolder.java109
-rw-r--r--src/com/android/camera/CameraManager.java5
-rwxr-xr-xsrc/com/android/camera/CameraSettings.java663
-rwxr-xr-xsrc/com/android/camera/CaptureModule.java136
-rwxr-xr-xsrc/com/android/camera/CaptureUI.java143
-rwxr-xr-xsrc/com/android/camera/ComboPreferences.java5
-rw-r--r--src/com/android/camera/CountDownTimerPreference.java4
-rw-r--r--src/com/android/camera/DisableCameraReceiver.java30
-rw-r--r--src/com/android/camera/FocusOverlayManager.java310
-rw-r--r--src/com/android/camera/FocusStateListener.java14
-rw-r--r--src/com/android/camera/ListPreference.java7
-rwxr-xr-xsrc/com/android/camera/LocationManager.java2
-rw-r--r--src/com/android/camera/MenuController.java1
-rw-r--r--src/com/android/camera/Mosaic.java2
-rw-r--r--src/com/android/camera/MosaicFrameProcessor.java2
-rw-r--r--src/com/android/camera/MosaicRenderer.java2
-rw-r--r--src/com/android/camera/OnScreenIndicators.java203
-rw-r--r--src/com/android/camera/PanoCaptureUI.java16
-rw-r--r--src/com/android/camera/PanoProgressBar.java4
-rwxr-xr-xsrc/com/android/camera/PermissionsActivity.java4
-rw-r--r--src/com/android/camera/PhotoMenu.java118
-rw-r--r--src/com/android/camera/PhotoModule.java906
-rwxr-xr-xsrc/com/android/camera/PhotoUI.java192
-rw-r--r--src/com/android/camera/PreviewGestures.java24
-rw-r--r--src/com/android/camera/SceneModeActivity.java4
-rwxr-xr-xsrc/com/android/camera/SettingsManager.java60
-rw-r--r--src/com/android/camera/ShutterButton.java49
-rw-r--r--src/com/android/camera/SoundPlayer.java95
-rw-r--r--src/com/android/camera/VideoController.java2
-rw-r--r--src/com/android/camera/VideoMenu.java71
-rw-r--r--src/com/android/camera/VideoModule.java382
-rwxr-xr-xsrc/com/android/camera/VideoUI.java71
-rw-r--r--src/com/android/camera/WideAnglePanoramaModule.java148
-rw-r--r--src/com/android/camera/WideAnglePanoramaUI.java62
-rw-r--r--src/com/android/camera/app/CameraApp.java8
-rw-r--r--src/com/android/camera/async/HandlerExecutor.java37
-rw-r--r--src/com/android/camera/async/MainThread.java47
-rw-r--r--src/com/android/camera/crop/CropActivity.java13
-rw-r--r--src/com/android/camera/crop/SaveImage.java15
-rw-r--r--src/com/android/camera/data/AbstractLocalDataAdapterWrapper.java5
-rwxr-xr-xsrc/com/android/camera/data/CameraDataAdapter.java21
-rw-r--r--src/com/android/camera/data/LocalDataAdapter.java3
-rw-r--r--src/com/android/camera/exif/ExifInterface.java11
-rw-r--r--src/com/android/camera/exif/ExifOutputStream.java2
-rwxr-xr-xsrc/com/android/camera/imageprocessor/PostProcessor.java41
-rw-r--r--src/com/android/camera/tinyplanet/TinyPlanetNative.java2
-rw-r--r--src/com/android/camera/ui/Arrows.java91
-rw-r--r--src/com/android/camera/ui/CameraControls.java39
-rw-r--r--src/com/android/camera/ui/FilmStripView.java4
-rw-r--r--src/com/android/camera/ui/ListMenu.java20
-rw-r--r--src/com/android/camera/ui/MenuHelp.java387
-rw-r--r--src/com/android/camera/ui/ModuleSwitcher.java16
-rwxr-xr-xsrc/com/android/camera/ui/OneUICameraControls.java4
-rw-r--r--src/com/android/camera/ui/Switch.java2
-rwxr-xr-xsrc/com/android/camera/ui/ZoomRenderer.java65
-rw-r--r--src/com/android/camera/ui/focus/AutoFocusRing.java101
-rw-r--r--src/com/android/camera/ui/focus/CameraCoordinateTransformer.java109
-rw-r--r--src/com/android/camera/ui/focus/FocusController.java128
-rw-r--r--src/com/android/camera/ui/focus/FocusRing.java72
-rw-r--r--src/com/android/camera/ui/focus/FocusRingRenderer.java237
-rw-r--r--src/com/android/camera/ui/focus/FocusRingView.java211
-rw-r--r--src/com/android/camera/ui/focus/FocusSound.java47
-rw-r--r--src/com/android/camera/ui/focus/LensRangeCalculator.java71
-rw-r--r--src/com/android/camera/ui/focus/ManualFocusRing.java93
-rw-r--r--src/com/android/camera/ui/motion/AnimationClock.java39
-rw-r--r--src/com/android/camera/ui/motion/DampedSpring.java145
-rw-r--r--src/com/android/camera/ui/motion/DynamicAnimation.java41
-rw-r--r--src/com/android/camera/ui/motion/DynamicAnimator.java116
-rw-r--r--src/com/android/camera/ui/motion/InterpolateUtils.java66
-rw-r--r--src/com/android/camera/ui/motion/InterpolatorHelper.java38
-rw-r--r--src/com/android/camera/ui/motion/Invalidator.java28
-rw-r--r--src/com/android/camera/ui/motion/LinearScale.java85
-rw-r--r--src/com/android/camera/ui/motion/UnitBezier.java157
-rw-r--r--src/com/android/camera/ui/motion/UnitCurve.java41
-rw-r--r--src/com/android/camera/ui/motion/UnitCurves.java44
-rwxr-xr-xsrc/com/android/camera/util/CameraUtil.java145
-rw-r--r--src/com/android/camera/util/MultiMap.java45
-rw-r--r--src/com/android/camera/util/PersistUtil.java6
-rwxr-xr-xsrc/com/android/camera/util/VendorTagUtil.java2
82 files changed, 4704 insertions, 2256 deletions
diff --git a/src/com/android/camera/AndroidCameraManagerImpl.java b/src/com/android/camera/AndroidCameraManagerImpl.java
index cad136cde..414ff8101 100644
--- a/src/com/android/camera/AndroidCameraManagerImpl.java
+++ b/src/com/android/camera/AndroidCameraManagerImpl.java
@@ -21,10 +21,12 @@ import static com.android.camera.util.CameraUtil.Assert;
import java.io.IOException;
import android.annotation.TargetApi;
+import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.AutoFocusMoveCallback;
+import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.ErrorCallback;
import android.hardware.Camera.FaceDetectionListener;
import android.hardware.Camera.OnZoomChangeListener;
@@ -41,11 +43,13 @@ import android.util.Log;
import android.view.SurfaceHolder;
import android.hardware.Camera.CameraDataCallback;
import android.hardware.Camera.CameraMetaDataCallback;
+import com.android.camera.app.CameraApp;
import com.android.camera.util.ApiHelper;
import android.os.ConditionVariable;
import java.lang.reflect.Method;
import org.codeaurora.snapcam.wrapper.CameraWrapper;
+import org.codeaurora.snapcam.R;
/**
* A class to implement {@link CameraManager} of the Android camera framework.
@@ -99,6 +103,7 @@ class AndroidCameraManagerImpl implements CameraManager {
private static final int SEND_HISTOGRAM_DATA = 602;
//LONGSHOT
private static final int SET_LONGSHOT = 701;
+ private static final int STOP_LONGSHOT = 702;
private static final int SET_AUTO_HDR_MODE = 801;
//HAL1 version code
@@ -235,16 +240,36 @@ class AndroidCameraManagerImpl implements CameraManager {
try {
switch (msg.what) {
case OPEN_CAMERA:
- try {
- Method openMethod = Class.forName("android.hardware.Camera").getMethod(
- "openLegacy", int.class, int.class);
- mCamera = (android.hardware.Camera) openMethod.invoke(
- null, msg.arg1, CAMERA_HAL_API_VERSION_1_0);
- } catch (Exception e) {
- /* Retry with open if openLegacy doesn't exist/fails */
- Log.v(TAG, "openLegacy failed due to " + e.getMessage()
- + ", using open instead");
- mCamera = android.hardware.Camera.open(msg.arg1);
+ final int cameraId = msg.arg1;
+ Context context = CameraApp.getContext();
+
+ CameraHolder.CameraInfo info =
+ CameraHolder.instance().getCameraInfo()[cameraId];
+
+ final boolean isBackCamera =
+ info.facing == CameraHolder.CameraInfo.CAMERA_FACING_BACK;
+ final boolean isFrontCamera =
+ info.facing == CameraHolder.CameraInfo.CAMERA_FACING_FRONT;
+ final boolean useOpenLegacyForBackCamera = context.getResources()
+ .getBoolean(R.bool.back_camera_open_legacy);
+ final boolean useOpenLegacyForFrontCamera = context.getResources()
+ .getBoolean(R.bool.front_camera_open_legacy);
+
+ if (isBackCamera && useOpenLegacyForBackCamera ||
+ isFrontCamera && useOpenLegacyForFrontCamera) {
+ try {
+ Method openMethod = Class.forName("android.hardware.Camera")
+ .getMethod("openLegacy", int.class, int.class);
+ mCamera = (android.hardware.Camera) openMethod.invoke(null,
+ cameraId, CAMERA_HAL_API_VERSION_1_0);
+ } catch (Exception e) {
+ /* Retry with open if openLegacy doesn't exist/fails */
+ Log.v(TAG, "openLegacy failed due to " + e.getMessage()
+ + ", using open instead");
+ mCamera = android.hardware.Camera.open(cameraId);
+ }
+ } else {
+ mCamera = android.hardware.Camera.open(cameraId);
}
if (mCamera != null) {
@@ -256,7 +281,7 @@ class AndroidCameraManagerImpl implements CameraManager {
}
} else {
if (msg.obj != null) {
- ((CameraOpenErrorCallback) msg.obj).onDeviceOpenFailure(msg.arg1);
+ ((CameraOpenErrorCallback) msg.obj).onDeviceOpenFailure(cameraId);
}
}
return;
@@ -402,6 +427,10 @@ class AndroidCameraManagerImpl implements CameraManager {
CameraWrapper.setLongshot(mCamera, (Boolean) msg.obj);
break;
+ case STOP_LONGSHOT:
+ CameraWrapper.stopLongshot(mCamera);
+ break;
+
case SET_AUTO_HDR_MODE:
CameraWrapper.setMetadataCb(mCamera, (CameraMetaDataCallback) msg.obj);
break;
@@ -663,6 +692,11 @@ class AndroidCameraManagerImpl implements CameraManager {
}
@Override
+ public void stopLongshot() {
+ mCameraHandler.sendEmptyMessage(STOP_LONGSHOT);
+ }
+
+ @Override
public void setHistogramMode(CameraDataCallback cb) {
mCameraHandler.obtainMessage(SET_HISTOGRAM_MODE, cb).sendToTarget();
}
diff --git a/src/com/android/camera/BestpictureActivity.java b/src/com/android/camera/BestpictureActivity.java
index 6eaa2a3d0..e4c1ca073 100644
--- a/src/com/android/camera/BestpictureActivity.java
+++ b/src/com/android/camera/BestpictureActivity.java
@@ -411,7 +411,8 @@ public class BestpictureActivity extends FragmentActivity {
@Override
public String getContentString() {
- return getResources().getString(R.string.save_best_dialog_content, choosenCount);
+ return getResources().getQuantityString(R.plurals.save_best_dialog_content,
+ choosenCount, choosenCount);
}
@Override
@@ -496,8 +497,8 @@ public class BestpictureActivity extends FragmentActivity {
}
}
}
- String toastString = getResources().getString(R.string.save_best_image_toast,
- toSaveCount);
+ String toastString = getResources().getQuantityString(R.plurals.save_best_image_toast,
+ toSaveCount, toSaveCount);
Toast.makeText(BestpictureActivity.this, toastString, Toast.LENGTH_SHORT).show();
backToViewfinder();
}
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 9e1855ff3..2933ed4e5 100755
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013-2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -120,6 +121,8 @@ import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper;
import com.android.camera.util.UsageStatistics;
import org.codeaurora.snapcam.R;
+import org.lineageos.quickreader.ScannerActivity;
+
import java.io.File;
import java.io.IOException;
@@ -169,7 +172,7 @@ public class CameraActivity extends Activity
private static final int SWITCH_SAVE_PATH = 2;
/** Permission request code */
- private static final int PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 1;
+ private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
/** Whether onResume should reset the view to the preview. */
private boolean mResetToPreviewOnResume = true;
@@ -192,11 +195,15 @@ public class CameraActivity extends Activity
private static boolean PIE_MENU_ENABLED = false;
private boolean mDeveloperMenuEnabled = false;
+ private boolean mCamera2supported = false;
+ private boolean mCamera2enabled = false;
+
/** This data adapter is used by FilmStripView. */
private LocalDataAdapter mDataAdapter;
/** This data adapter represents the real local camera data. */
private LocalDataAdapter mWrappedDataAdapter;
+ private Context mContext;
private PanoramaStitchingManager mPanoramaManager;
private PlaceholderManager mPlaceholderManager;
private int mCurrentModuleIndex;
@@ -221,6 +228,11 @@ public class CameraActivity extends Activity
private final Object mStorageSpaceLock = new Object();
private long mStorageSpaceBytes = Storage.LOW_STORAGE_THRESHOLD_BYTES;
private boolean mSecureCamera;
+ private boolean mInCameraApp = true;
+ // Keep track of powershutter state
+ public static boolean mPowerShutter = false;
+ // Keep track of max brightness state
+ public static boolean mMaxBrightness = false;
private int mLastRawOrientation;
private MyOrientationEventListener mOrientationListener;
private Handler mMainHandler;
@@ -390,6 +402,10 @@ public class CameraActivity extends Activity
mDeveloperMenuEnabled = true;
}
+ public void disableDeveloperMenu() {
+ mDeveloperMenuEnabled = false;
+ }
+
private String fileNameFromDataID(int dataID) {
final LocalData localData = mDataAdapter.getLocalData(dataID);
@@ -610,14 +626,36 @@ public class CameraActivity extends Activity
intent.putExtra(KEY_TOTAL_NUMBER, (adapter.getTotalNumber() -1));
startActivity(intent);
} catch (ActivityNotFoundException ex) {
- try {
- Log.w(TAG, "Gallery not found");
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- intent.putExtra(KEY_FROM_SNAPCAM, true);
- startActivity(intent);
- } catch (ActivityNotFoundException e) {
- Log.w(TAG, "No Activity could be found to open image or video");
- }
+ gotoReviewPhoto(uri);
+ } catch (IllegalArgumentException ex) {
+ gotoReviewPhoto(uri);
+ }
+ }
+
+ private void gotoReviewPhoto(Uri uri) {
+ try {
+ Log.w(TAG, "Gallery not found");
+ Intent intent = new Intent(CameraUtil.REVIEW_ACTION, uri);
+ startActivity(intent);
+ intent.putExtra(KEY_FROM_SNAPCAM, true);
+ intent.putExtra(KEY_TOTAL_NUMBER, getDataAdapter().getTotalNumber() - 1);
+ } catch (ActivityNotFoundException e) {
+ gotoViewPhoto(uri);
+ } catch (IllegalArgumentException e) {
+ gotoViewPhoto(uri);
+ }
+ }
+
+ private void gotoViewPhoto(Uri uri) {
+ try {
+ Log.w(TAG, "Gallery not found");
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ intent.putExtra(KEY_FROM_SNAPCAM, true);
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "No Activity could be found to open image or video");
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "No Activity could be found to open image or video");
}
}
@@ -1343,14 +1381,8 @@ public class CameraActivity extends Activity
// Handle presses on the action bar items
switch (item.getItemId()) {
case android.R.id.home:
- // ActionBar's Up/Home button was clicked
- try {
- startActivity(IntentHelper.getGalleryIntent(this));
- return true;
- } catch (ActivityNotFoundException e) {
- Log.w(TAG, "Failed to launch gallery activity, closing");
- finish();
- }
+ onBackPressed();
+ return true;
case R.id.action_delete:
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_DELETE, null, 0,
@@ -1465,6 +1497,9 @@ public class CameraActivity extends Activity
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
+
+ mContext = getApplicationContext();
+
// Check if this is in the secure camera mode.
Intent intent = getIntent();
String action = intent.getAction();
@@ -1541,9 +1576,16 @@ public class CameraActivity extends Activity
}
}
- boolean cam2on = PersistUtil.getCamera2Mode();
- CameraHolder.setCamera2Mode(this, cam2on);
- if (cam2on && (moduleIndex == ModuleSwitcher.PHOTO_MODULE_INDEX ||
+ // Check if the device supports Camera API 2
+ mCamera2supported = CameraUtil.isCamera2Supported(mContext);
+ Log.d(TAG, "Camera API 2 supported: " + mCamera2supported);
+
+ mCamera2enabled = mCamera2supported &&
+ mContext.getResources().getBoolean(R.bool.support_camera_api_v2);
+ Log.d(TAG, "Camera API 2 enabled: " + mCamera2enabled);
+
+ CameraHolder.setCamera2Mode(this, mCamera2enabled);
+ if (mCamera2enabled && (moduleIndex == ModuleSwitcher.PHOTO_MODULE_INDEX ||
moduleIndex == ModuleSwitcher.VIDEO_MODULE_INDEX))
moduleIndex = ModuleSwitcher.CAPTURE_MODULE_INDEX;
@@ -1899,6 +1941,9 @@ public class CameraActivity extends Activity
mCursor.close();
mCursor=null;
}
+ if (mDataAdapter != null) {
+ mDataAdapter.stopLoading();
+ }
if (mAutoTestEnabled) {
unregisterReceiver(mAutoTestReceiver);
}
@@ -1949,7 +1994,9 @@ public class CameraActivity extends Activity
}
public void setPreviewGestures(PreviewGestures previewGestures) {
- mFilmStripView.setPreviewGestures(previewGestures);
+ if (mFilmStripView != null) {
+ mFilmStripView.setPreviewGestures(previewGestures);
+ }
}
protected long updateStorageSpace() {
@@ -2024,6 +2071,39 @@ public class CameraActivity extends Activity
}
}
+ protected void initPowerShutter(ComboPreferences prefs) {
+ String val = prefs.getString(CameraSettings.KEY_POWER_SHUTTER,
+ getResources().getString(R.string.pref_camera_power_shutter_default));
+ if (!CameraUtil.hasCameraKey()) {
+ mPowerShutter = val.equals(CameraSettings.VALUE_ON);
+ }
+ if (mPowerShutter && mInCameraApp) {
+ getWindow().addPrivateFlags(
+ WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY);
+ } else {
+ getWindow().clearPrivateFlags(
+ WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY);
+ }
+ }
+
+ protected void initMaxBrightness(ComboPreferences prefs) {
+ String val = prefs.getString(CameraSettings.KEY_MAX_BRIGHTNESS,
+ getResources().getString(R.string.pref_camera_max_brightness_default));
+
+ Window win = getWindow();
+ WindowManager.LayoutParams params = win.getAttributes();
+
+ mMaxBrightness = val.equals(CameraSettings.VALUE_ON);
+
+ if (mMaxBrightness && mInCameraApp) {
+ params.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL;
+ } else {
+ params.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
+ }
+
+ win.setAttributes(params);
+ }
+
protected void setResultEx(int resultCode) {
mResultCodeForTesting = resultCode;
setResult(resultCode);
@@ -2048,13 +2128,13 @@ public class CameraActivity extends Activity
}
public void requestLocationPermission() {
- if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
+ if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
Log.v(TAG, "Request Location permission");
mCurrentModule.waitingLocationPermissionResult(true);
requestPermissions(
- new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
- PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
+ new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
+ PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
}
@@ -2062,7 +2142,7 @@ public class CameraActivity extends Activity
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
- case PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION: {
+ case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
// If request is cancelled, the result arrays are empty.
mCurrentModule.waitingLocationPermissionResult(false);
if (grantResults.length > 0
@@ -2082,11 +2162,21 @@ public class CameraActivity extends Activity
return mForceReleaseCamera;
}
+ public boolean isInCameraApp() {
+ return mInCameraApp;
+ }
+
@Override
public void onModuleSelected(int moduleIndex) {
- boolean cam2on = PersistUtil.getCamera2Mode();
+ if (moduleIndex == ModuleSwitcher.QR_MODULE_INDEX) {
+ Intent intent = new Intent(this, ScannerActivity.class);
+ intent.putExtra(SECURE_CAMERA_EXTRA, mSecureCamera);
+ startActivity(intent);
+ return;
+ }
+
mForceReleaseCamera = moduleIndex == ModuleSwitcher.CAPTURE_MODULE_INDEX ||
- (cam2on && moduleIndex == ModuleSwitcher.PHOTO_MODULE_INDEX);
+ (mCamera2enabled && moduleIndex == ModuleSwitcher.PHOTO_MODULE_INDEX);
if (mForceReleaseCamera) {
moduleIndex = ModuleSwitcher.CAPTURE_MODULE_INDEX;
}
@@ -2358,6 +2448,9 @@ public class CameraActivity extends Activity
* @return whether controls are visible.
*/
private boolean arePreviewControlsVisible() {
+ if (mCurrentModule == null) {
+ return false;
+ }
return mCurrentModule.arePreviewControlsVisible();
}
@@ -2369,6 +2462,10 @@ public class CameraActivity extends Activity
*/
private void setPreviewControlsVisibility(boolean showControls) {
mCurrentModule.onPreviewFocusChanged(showControls);
+
+ // controls are only shown when the camera app is active
+ // so we can assume to fetch this information from here
+ mInCameraApp = showControls;
}
// Accessor methods for getting latency times used in performance testing
diff --git a/src/com/android/camera/CameraHolder.java b/src/com/android/camera/CameraHolder.java
index 59b305bc6..585e3bb4d 100755
--- a/src/com/android/camera/CameraHolder.java
+++ b/src/com/android/camera/CameraHolder.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 The Android Open Source Project
+ * 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,8 +31,11 @@ import android.os.Looper;
import android.os.Message;
import android.util.Log;
+import com.android.camera.app.CameraApp;
import com.android.camera.CameraManager.CameraProxy;
+import org.codeaurora.snapcam.R;
+
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -64,11 +68,11 @@ public class CameraHolder {
private static CameraProxy mMockCamera[];
private static CameraInfo mMockCameraInfo[];
private static Context mContext;
- private static boolean mCam2On = true;
+ private static boolean mCam2On = false;
private ArrayList<CameraCharacteristics> mCharacteristics = new ArrayList<>();
/* Debug double-open issue */
- private static final boolean DEBUG_OPEN_RELEASE = true;
+ private static final boolean DEBUG_OPEN_RELEASE = false;
private static class OpenReleaseState {
long time;
int id;
@@ -169,52 +173,46 @@ public class CameraHolder {
HandlerThread ht = new HandlerThread("CameraHolder");
ht.start();
mHandler = new MyHandler(ht.getLooper());
- if (mCam2On) {
- android.hardware.camera2.CameraManager manager =
- (android.hardware.camera2.CameraManager) mContext.getSystemService(
- Context.CAMERA_SERVICE);
- String[] cameraIdList = null;
- try {
- cameraIdList = manager.getCameraIdList();
- for (int i = 0; i < cameraIdList.length; i++) {
- String cameraId = cameraIdList[i];
- CameraCharacteristics characteristics
- = manager.getCameraCharacteristics(cameraId);
- Log.d(TAG,"cameraIdList size ="+cameraIdList.length);
- int facing = characteristics.get(CameraCharacteristics.LENS_FACING);
- if (facing == CameraCharacteristics.LENS_FACING_FRONT) {
- CaptureModule.FRONT_ID = i;
- }
- mCharacteristics.add(i, characteristics);
+ android.hardware.camera2.CameraManager manager =
+ (android.hardware.camera2.CameraManager) mContext.getSystemService(
+ Context.CAMERA_SERVICE);
+ String[] cameraIdList = null;
+ try {
+ cameraIdList = manager.getCameraIdList();
+ mInfo = new CameraInfo[cameraIdList.length];
+ for (int i = 0; i < cameraIdList.length; i++) {
+ String cameraId = cameraIdList[i];
+ CameraCharacteristics characteristics
+ = manager.getCameraCharacteristics(cameraId);
+ Log.d(TAG,"cameraIdList size ="+cameraIdList.length);
+ int facing = characteristics.get(CameraCharacteristics.LENS_FACING);
+ if (facing == CameraCharacteristics.LENS_FACING_FRONT) {
+ CaptureModule.FRONT_ID = i;
}
- } catch (CameraAccessException e) {
- e.printStackTrace();
+ addCameraInfo(i, characteristics);
+ mCharacteristics.add(i, characteristics);
}
- mNumberOfCameras = cameraIdList == null ? 0 : cameraIdList.length;
- } else {
- if (mMockCameraInfo != null) {
- mNumberOfCameras = mMockCameraInfo.length;
- mInfo = mMockCameraInfo;
- } else {
- mNumberOfCameras = android.hardware.Camera.getNumberOfCameras();
- mInfo = new CameraInfo[mNumberOfCameras];
- for (int i = 0; i < mNumberOfCameras; i++) {
- mInfo[i] = new CameraInfo();
- android.hardware.Camera.getCameraInfo(i, mInfo[i]);
- }
- }
- // get the first (smallest) back and first front camera id
- for (int i = 0; i < mNumberOfCameras; i++) {
- if (mBackCameraId == -1 && mInfo[i].facing == CameraInfo.CAMERA_FACING_BACK) {
- mBackCameraId = i;
- } else if (mFrontCameraId == -1 &&
- mInfo[i].facing == CameraInfo.CAMERA_FACING_FRONT) {
- mFrontCameraId = i;
- }
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ mNumberOfCameras = cameraIdList == null ? 0 : cameraIdList.length;
+ // get the first (smallest) back and first front camera id
+ for (int i = 0; i < mNumberOfCameras; i++) {
+ if (mBackCameraId == -1 && mInfo[i].facing == CameraCharacteristics.LENS_FACING_BACK) {
+ mBackCameraId = i;
+ } else if (mFrontCameraId == -1 &&
+ mInfo[i].facing == CameraCharacteristics.LENS_FACING_FRONT) {
+ mFrontCameraId = i;
}
}
}
+ private void addCameraInfo(int index, CameraCharacteristics characteristics) {
+ mInfo[index] = new CameraInfo();
+ mInfo[index].facing = characteristics.get(CameraCharacteristics.LENS_FACING);
+ mInfo[index].orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
+ }
+
public CameraCharacteristics getCameraCharacteristics(int id) {
return mCharacteristics.get(id);
}
@@ -230,6 +228,9 @@ public class CameraHolder {
public synchronized CameraProxy open(
Handler handler, int cameraId,
CameraManager.CameraOpenErrorCallback cb) {
+
+ Context context = CameraApp.getContext();
+
if (DEBUG_OPEN_RELEASE) {
collectState(cameraId, mCameraDevice);
if (mCameraOpened) {
@@ -262,6 +263,23 @@ public class CameraHolder {
}
mCameraId = cameraId;
mParameters = mCameraDevice.getCamera().getParameters();
+
+ // Manufacturer specific key values
+ String manufacturerKeyValues =
+ context.getResources().getString(R.string.manufacturer_key_values);
+ if (manufacturerKeyValues != null && !manufacturerKeyValues.isEmpty()) {
+ String[] keyValuesArray = manufacturerKeyValues.split(";");
+ for (String kvPair : keyValuesArray) {
+ String[] manufacturerParamPair = kvPair.split("=");
+ if (!manufacturerParamPair[0].isEmpty() &&
+ !manufacturerParamPair[1].isEmpty()) {
+ Log.d(TAG, "Set manufacturer specific parameter " +
+ manufacturerParamPair[0] + "=" + manufacturerParamPair[1]);
+ mParameters.set(manufacturerParamPair[0], manufacturerParamPair[1]);
+ }
+ }
+ mCameraDevice.setParameters(mParameters);
+ }
} else {
if (!mCameraDevice.reconnect(handler, cb)) {
Log.e(TAG, "fail to reconnect Camera:" + mCameraId + ", aborting.");
@@ -334,4 +352,11 @@ public class CameraHolder {
public int getFrontCameraId() {
return mFrontCameraId;
}
+
+ public class CameraInfo {
+ public static final int CAMERA_FACING_FRONT = CameraCharacteristics.LENS_FACING_FRONT;
+ public static final int CAMERA_FACING_BACK = CameraCharacteristics.LENS_FACING_BACK;
+ public int facing;
+ public int orientation;
+ }
}
diff --git a/src/com/android/camera/CameraManager.java b/src/com/android/camera/CameraManager.java
index b93e7182b..2aeba7c5d 100644
--- a/src/com/android/camera/CameraManager.java
+++ b/src/com/android/camera/CameraManager.java
@@ -384,5 +384,10 @@ public interface CameraManager {
* {@code false} to disable it.
*/
public void setLongshot(boolean enable);
+ /**
+ * Stop longshot.
+ *
+ */
+ public void stopLongshot();
}
}
diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java
index 9a0a8219b..ab4b1a6a4 100755
--- a/src/com/android/camera/CameraSettings.java
+++ b/src/com/android/camera/CameraSettings.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2013-2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,11 +40,14 @@ import com.android.camera.util.ApiHelper;
import com.android.camera.util.CameraUtil;
import com.android.camera.util.GcamHelper;
import com.android.camera.util.PersistUtil;
+import com.android.camera.util.MultiMap;
+
import org.codeaurora.snapcam.R;
import org.codeaurora.snapcam.wrapper.CamcorderProfileWrapper;
import org.codeaurora.snapcam.wrapper.ParametersWrapper;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Locale;
import android.os.Build;
@@ -64,6 +68,9 @@ public class CameraSettings {
public static final String KEY_PICTURE_SIZE = "pref_camera_picturesize_key";
public static final String KEY_JPEG_QUALITY = "pref_camera_jpegquality_key";
public static final String KEY_FOCUS_MODE = "pref_camera_focusmode_key";
+ public static final String KEY_VIDEOCAMERA_FOCUS_MODE = "pref_camera_video_focusmode_key";
+ public static final String KEY_FOCUS_TIME = "pref_camera_focustime_key";
+ public static final String KEY_VIDEOCAMERA_FOCUS_TIME = "pref_camera_video_focustime_key";
public static final String KEY_FLASH_MODE = "pref_camera_flashmode_key";
public static final String KEY_VIDEOCAMERA_FLASH_MODE = "pref_camera_video_flashmode_key";
public static final String KEY_WHITE_BALANCE = "pref_camera_whitebalance_key";
@@ -81,17 +88,18 @@ public class CameraSettings {
public static final String KEY_PHOTOSPHERE_PICTURESIZE = "pref_photosphere_picturesize_key";
public static final String KEY_STARTUP_MODULE_INDEX = "camera.startup_module";
+ public static final String KEY_POWER_SHUTTER = "pref_power_shutter";
+ public static final String KEY_MAX_BRIGHTNESS = "pref_max_brightness";
public static final String KEY_VIDEO_ENCODER = "pref_camera_videoencoder_key";
public static final String KEY_AUDIO_ENCODER = "pref_camera_audioencoder_key";
- public static final String KEY_VIDEO_DURATION = "pref_camera_video_duration_key";
public static final String KEY_POWER_MODE = "pref_camera_powermode_key";
public static final String KEY_PICTURE_FORMAT = "pref_camera_pictureformat_key";
public static final String KEY_ZSL = "pref_camera_zsl_key";
public static final String KEY_CAMERA_SAVEPATH = "pref_camera_savepath_key";
public static final String KEY_FILTER_MODE = "pref_camera_filter_mode_key";
public static final String KEY_COLOR_EFFECT = "pref_camera_coloreffect_key";
+ public static final String KEY_VIDEOCAMERA_COLOR_EFFECT = "pref_camera_video_coloreffect_key";
public static final String KEY_FACE_DETECTION = "pref_camera_facedetection_key";
- public static final String KEY_TOUCH_AF_AEC = "pref_camera_touchafaec_key";
public static final String KEY_SELECTABLE_ZONE_AF = "pref_camera_selectablezoneaf_key";
public static final String KEY_SATURATION = "pref_camera_saturation_key";
public static final String KEY_CONTRAST = "pref_camera_contrast_key";
@@ -99,6 +107,7 @@ public class CameraSettings {
public static final String KEY_AUTOEXPOSURE = "pref_camera_autoexposure_key";
public static final String KEY_ANTIBANDING = "pref_camera_antibanding_key";
public static final String KEY_ISO = "pref_camera_iso_key";
+ public static final String KEY_SHUTTER_SPEED = "pref_camera_shutter_speed_key";
public static final String KEY_LENSSHADING = "pref_camera_lensshading_key";
public static final String KEY_HISTOGRAM = "pref_camera_histogram_key";
public static final String KEY_DENOISE = "pref_camera_denoise_key";
@@ -113,7 +122,6 @@ public class CameraSettings {
public static final String KEY_AE_BRACKET_HDR = "pref_camera_ae_bracket_hdr_key";
public static final String KEY_ADVANCED_FEATURES = "pref_camera_advanced_features_key";
public static final String KEY_HDR_MODE = "pref_camera_hdr_mode_key";
- public static final String KEY_HDR_NEED_1X = "pref_camera_hdr_need_1x_key";
public static final String KEY_DEVELOPER_MENU = "pref_developer_menu_key";
public static final String KEY_VIDEO_SNAPSHOT_SIZE = "pref_camera_videosnapsize_key";
@@ -153,8 +161,10 @@ public class CameraSettings {
private static final String KEY_QC_SUPPORTED_VIDEO_CDS_MODES = "video-cds-mode-values";
private static final String KEY_QC_SUPPORTED_TNR_MODES = "tnr-mode-values";
private static final String KEY_QC_SUPPORTED_VIDEO_TNR_MODES = "video-tnr-mode-values";
+ private static final String KEY_QC_SUPPORTED_FACE_DETECTION = "face-detection-values";
private static final String KEY_SNAPCAM_SUPPORTED_HDR_MODES = "hdr-mode-values";
- private static final String KEY_SNAPCAM_SUPPORTED_HDR_NEED_1X = "hdr-need-1x-values";
+ public static final String KEY_SNAPCAM_SHUTTER_SPEED = "shutter-speed";
+ public static final String KEY_SNAPCAM_SHUTTER_SPEED_MODES = "shutter-speed-values";
public static final String KEY_QC_AE_BRACKETING = "ae-bracket-hdr";
public static final String KEY_QC_AF_BRACKETING = "af-bracket";
public static final String KEY_QC_RE_FOCUS = "re-focus";
@@ -173,13 +183,19 @@ public class CameraSettings {
public static final String KEY_QC_TNR_MODE = "tnr-mode";
public static final String KEY_QC_VIDEO_TNR_MODE = "video-tnr-mode";
public static final String KEY_SNAPCAM_HDR_MODE = "hdr-mode";
- public static final String KEY_SNAPCAM_HDR_NEED_1X = "hdr-need-1x";
public static final String KEY_VIDEO_HSR = "video-hsr";
public static final String KEY_QC_SEE_MORE_MODE = "see-more";
public static final String KEY_QC_NOISE_REDUCTION_MODE = "noise-reduction-mode";
public static final String KEY_QC_INSTANT_CAPTURE = "instant-capture";
public static final String KEY_QC_INSTANT_CAPTURE_VALUES = "instant-capture-values";
+ public static final String KEY_LUMINANCE_CONDITION = "luminance-condition";
+ public static final String LUMINANCE_CONDITION_LOW = "low";
+ public static final String LUMINANCE_CONDITION_HIGH = "high";
+
+ public static final String LGE_HDR_MODE_OFF = "0";
+ public static final String LGE_HDR_MODE_ON = "1";
+
public static final String KEY_INTERNAL_PREVIEW_RESTART = "internal-restart";
public static final String KEY_QC_ZSL_HDR_SUPPORTED = "zsl-hdr-supported";
public static final String KEY_QC_LONGSHOT_SUPPORTED = "longshot-supported";
@@ -201,10 +217,6 @@ public class CameraSettings {
private static final String KEY_QC_PICTURE_FORMAT = "picture-format-values";
public static final String KEY_VIDEO_ROTATION = "pref_camera_video_rotation_key";
- private static final String VIDEO_QUALITY_HIGH = "high";
- private static final String VIDEO_QUALITY_MMS = "mms";
- private static final String VIDEO_QUALITY_YOUTUBE = "youtube";
-
//manual 3A keys and parameter strings
public static final String KEY_MANUAL_EXPOSURE = "pref_camera_manual_exp_key";
@@ -268,28 +280,29 @@ public class CameraSettings {
public static final String KEY_REFOCUS_PROMPT = "refocus-prompt";
- public static final String KEY_SHOW_MENU_HELP = "help_menu";
-
public static final String KEY_REQUEST_PERMISSION = "request_permission";
public static final String KEY_SELFIE_FLASH = "pref_selfie_flash_key";
public static final String EXPOSURE_DEFAULT_VALUE = "0";
+ public static final String VALUE_ON = "on";
+ public static final String VALUE_OFF = "off";
public static final int CURRENT_VERSION = 5;
public static final int CURRENT_LOCAL_VERSION = 2;
- public static final int DEFAULT_VIDEO_DURATION = 0; // no limit
- private static final int MMS_VIDEO_DURATION = (CamcorderProfile.get(CamcorderProfile.QUALITY_LOW) != null) ?
- CamcorderProfile.get(CamcorderProfile.QUALITY_LOW).duration :30;
- private static final int YOUTUBE_VIDEO_DURATION = 15 * 60; // 15 mins
-
private static final String TAG = "CameraSettings";
private final Context mContext;
private final Parameters mParameters;
- private final CameraInfo[] mCameraInfo;
+ private final CameraHolder.CameraInfo[] mCameraInfo;
private final int mCameraId;
+
+ public static String mKeyIso = null;
+ public static String mKeyIsoValues = null;
+
+ private static boolean mSupportBokehMode = false;
+
private static final HashMap<Integer, String>
VIDEO_ENCODER_TABLE = new HashMap<Integer, String>();
public static final HashMap<String, Integer>
@@ -438,11 +451,30 @@ public class CameraSettings {
}
public CameraSettings(Activity activity, Parameters parameters,
- int cameraId, CameraInfo[] cameraInfo) {
+ int cameraId, CameraHolder.CameraInfo[] cameraInfo) {
mContext = activity;
mParameters = parameters;
mCameraId = cameraId;
mCameraInfo = cameraInfo;
+
+ // ISO
+ mKeyIso = mContext.getResources().getString(R.string.key_iso);
+ mKeyIsoValues = mContext.getResources().getString(R.string.key_iso_values);
+
+ if (mKeyIso == null || mKeyIso.isEmpty()) {
+ mKeyIso = "iso";
+ } else {
+ Log.d(TAG, "Using key for iso: " + mKeyIso);
+ }
+
+ if (mKeyIsoValues == null || mKeyIsoValues.isEmpty()) {
+ mKeyIsoValues = "iso-values";
+ } else {
+ Log.d(TAG, "Using key for iso-values: " + mKeyIsoValues);
+ }
+
+ // Bokeh mode
+ mSupportBokehMode = mContext.getResources().getBoolean(R.bool.support_bokeh_mode);
}
public PreferenceGroup getPreferenceGroup(int preferenceRes) {
@@ -453,35 +485,88 @@ public class CameraSettings {
return group;
}
+ public static List<String> getSupportedIsoValues(Parameters params) {
+ String isoValues = params.get(mKeyIsoValues);
+ if (isoValues == null) {
+ return null;
+ }
+ Log.d(TAG, "Supported iso values: " + isoValues);
+ return split(isoValues);
+ }
+
+ public static String getISOValue(Parameters params) {
+ String iso = params.get(mKeyIso);
+
+ if (iso == null) {
+ return null;
+ }
+ return iso;
+ }
+
+ public static void setISOValue(Parameters params, String iso) {
+ params.set(mKeyIso, iso);
+ }
+
+ public static List<String> getSupportedShutterSpeedValues(Parameters params) {
+ String shutterSpeedValues = params.get(KEY_SNAPCAM_SHUTTER_SPEED_MODES);
+ if (shutterSpeedValues == null) {
+ return null;
+ }
+ Log.d(TAG, "Supported shutter speed values: " + shutterSpeedValues);
+ return split(shutterSpeedValues);
+ }
+
public static String getSupportedHighestVideoQuality(
- int cameraId, Parameters parameters) {
+ Context context, int cameraId, Parameters parameters) {
// When launching the camera app first time, we will set the video quality
// to the first one (i.e. highest quality) in the supported list
List<String> supported = getSupportedVideoQualities(cameraId,parameters);
assert (supported != null) : "No supported video quality is found";
+ for (String candidate : context.getResources().getStringArray(
+ R.array.pref_video_quality_entryvalues)) {
+ if (supported.indexOf(candidate) >= 0) {
+ return candidate;
+ }
+ }
+ Log.w(TAG, "No supported video size matches, using the first reported size");
return supported.get(0);
}
- public static void initialCameraPictureSize(
- Context context, Parameters parameters) {
- // When launching the camera app first time, we will set the picture
- // size to the first one in the list defined in "arrays.xml" and is also
- // supported by the driver.
+ public static void initialCameraPictureSize(Context context, Parameters parameters) {
+ // set the picture size to the largest supported size
List<Size> supported = parameters.getSupportedPictureSizes();
- if (supported == null) return;
- for (String candidate : context.getResources().getStringArray(
- R.array.pref_camera_picturesize_entryvalues)) {
- if (setCameraPictureSize(candidate, supported, parameters)) {
- SharedPreferences.Editor editor = ComboPreferences
- .get(context).edit();
- editor.putString(KEY_PICTURE_SIZE, candidate);
- editor.apply();
- return;
- }
+ if (supported == null || supported.isEmpty()) { return; }
+ Size largest = getLargestSize(supported);
+ String candidate = largest.width + "x" + largest.height;
+ if (setCameraPictureSize(candidate, supported, parameters)) {
+ SharedPreferences.Editor editor =
+ ComboPreferences.get(context).edit();
+ editor.putString(KEY_PICTURE_SIZE, candidate);
+ editor.apply();
+ return;
}
Log.e(TAG, "No supported picture size found");
}
+ private static Size getLargestSize(List<Size> sizes) {
+ if (sizes == null || sizes.isEmpty()) {
+ return null;
+ }
+
+ Size max = sizes.get(0);
+ int maxSize = max.width * max.height;
+
+ for (Size candidate : sizes) {
+ int candidateSize = candidate.width * candidate.height;
+ if (candidateSize > maxSize) {
+ maxSize = candidateSize;
+ max = candidate;
+ }
+ }
+
+ return max;
+ }
+
public static void removePreferenceFromScreen(
PreferenceGroup group, String key) {
removePreference(group, key);
@@ -519,6 +604,14 @@ public class CameraSettings {
return split(str);
}
+ public static List<String> getSupportedFaceDetection(Parameters params) {
+ String str = params.get(KEY_QC_SUPPORTED_FACE_DETECTION);
+ if (str == null) {
+ return null;
+ }
+ return split(str);
+ }
+
public static List<String> getSupportedDISModes(Parameters params) {
String str = params.get(KEY_QC_SUPPORTED_DIS_MODES);
if (str == null) {
@@ -591,14 +684,6 @@ public class CameraSettings {
return split(str);
}
- public static List<String> getSupportedHDRNeed1x(Parameters params) {
- String str = params.get(KEY_SNAPCAM_SUPPORTED_HDR_NEED_1X);
- if (str == null) {
- return null;
- }
- return split(str);
- }
-
public List<String> getSupportedAdvancedFeatures(Parameters params) {
String str = params.get(KEY_QC_SUPPORTED_AF_BRACKETING_MODES);
str += ',' + params.get(KEY_QC_SUPPORTED_CF_MODES);
@@ -700,7 +785,7 @@ public class CameraSettings {
private List<String> getSupportedPictureFormatLists() {
String str = mParameters.get(KEY_QC_PICTURE_FORMAT);
if (str == null) {
- str = "jpeg,raw"; // if not set, fall back to default behavior
+ return null;
}
return split(str);
}
@@ -731,21 +816,38 @@ public class CameraSettings {
ArrayList<String> supported = new ArrayList<String>();
int zoomMaxIdx = params.getMaxZoom();
List <Integer> zoomRatios = params.getZoomRatios();
- int zoomMax = zoomRatios.get(zoomMaxIdx)/100;
-
- for (int zoomLevel = 0; zoomLevel <= zoomMax; zoomLevel++) {
- supported.add(String.valueOf(zoomLevel));
+ if (zoomRatios != null ) {
+ int zoomMax = zoomRatios.get(zoomMaxIdx)/100;
+ for (int zoomLevel = 0; zoomLevel <= zoomMax; zoomLevel++) {
+ supported.add(String.valueOf(zoomLevel));
+ }
}
return supported;
}
+ private static ListPreference removeLeadingISO(ListPreference pref) {
+ CharSequence entryValues[] = pref.getEntryValues();
+ if (entryValues.length > 0) {
+ CharSequence modEntryValues[] = new CharSequence[entryValues.length];
+ for (int i = 0, len = entryValues.length; i < len; i++) {
+ String isoValue = entryValues[i].toString();
+ if (isoValue.startsWith("ISO") && !isoValue.startsWith("ISO_")) {
+ isoValue = isoValue.replaceAll("ISO", "");
+ }
+ modEntryValues[i] = isoValue;
+ }
+ pref.setEntryValues(modEntryValues);
+ }
+ return pref;
+ }
+
private void qcomInitPreferences(PreferenceGroup group){
//Qcom Preference add here
ListPreference powerMode = group.findPreference(KEY_POWER_MODE);
ListPreference zsl = group.findPreference(KEY_ZSL);
ListPreference colorEffect = group.findPreference(KEY_COLOR_EFFECT);
+ ListPreference camcorderColorEffect = group.findPreference(KEY_VIDEOCAMERA_COLOR_EFFECT);
ListPreference faceDetection = group.findPreference(KEY_FACE_DETECTION);
- ListPreference touchAfAec = group.findPreference(KEY_TOUCH_AF_AEC);
ListPreference selectableZoneAf = group.findPreference(KEY_SELECTABLE_ZONE_AF);
ListPreference saturation = group.findPreference(KEY_SATURATION);
ListPreference contrast = group.findPreference(KEY_CONTRAST);
@@ -753,6 +855,7 @@ public class CameraSettings {
ListPreference autoExposure = group.findPreference(KEY_AUTOEXPOSURE);
ListPreference antiBanding = group.findPreference(KEY_ANTIBANDING);
ListPreference mIso = group.findPreference(KEY_ISO);
+ ListPreference mShutterSpeed = group.findPreference(KEY_SHUTTER_SPEED);
ListPreference lensShade = group.findPreference(KEY_LENSSHADING);
ListPreference histogram = group.findPreference(KEY_HISTOGRAM);
ListPreference denoise = group.findPreference(KEY_DENOISE);
@@ -767,7 +870,6 @@ public class CameraSettings {
ListPreference longShot = group.findPreference(KEY_LONGSHOT);
ListPreference auto_hdr = group.findPreference(KEY_AUTO_HDR);
ListPreference hdr_mode = group.findPreference(KEY_HDR_MODE);
- ListPreference hdr_need_1x = group.findPreference(KEY_HDR_NEED_1X);
ListPreference cds_mode = group.findPreference(KEY_CDS_MODE);
ListPreference video_cds_mode = group.findPreference(KEY_VIDEO_CDS_MODE);
ListPreference tnr_mode = group.findPreference(KEY_TNR_MODE);
@@ -788,6 +890,12 @@ public class CameraSettings {
}
}
+ // Remove leading ISO from iso-values
+ boolean isoValuesUseNumbers = mContext.getResources().getBoolean(R.bool.iso_values_use_numbers);
+ if (isoValuesUseNumbers && mIso != null) {
+ mIso = removeLeadingISO(mIso);
+ }
+
if (bokehMode != null) {
if (!isBokehModeSupported(mParameters)) {
removePreference(group, bokehMode.getKey());
@@ -801,11 +909,6 @@ public class CameraSettings {
}
}
- if (hdr_need_1x != null) {
- filterUnsupportedOptions(group,
- hdr_need_1x, getSupportedHDRNeed1x(mParameters));
- }
-
if (hdr_mode != null) {
filterUnsupportedOptions(group,
hdr_mode, getSupportedHDRModes(mParameters));
@@ -833,11 +936,6 @@ public class CameraSettings {
ListPreference videoRotation = group.findPreference(KEY_VIDEO_ROTATION);
- if (touchAfAec != null) {
- filterUnsupportedOptions(group,
- touchAfAec, ParametersWrapper.getSupportedTouchAfAec(mParameters));
- }
-
if (!ParametersWrapper.isPowerModeSupported(mParameters) && powerMode != null) {
removePreference(group, powerMode.getKey());
}
@@ -847,9 +945,29 @@ public class CameraSettings {
selectableZoneAf, ParametersWrapper.getSupportedSelectableZoneAf(mParameters));
}
+ if (saturation != null && !CameraUtil.isSupported(mParameters, "saturation") &&
+ !CameraUtil.isSupported(mParameters, "max-saturation")) {
+ removePreference(group, saturation.getKey());
+ }
+
+ if (contrast != null && !CameraUtil.isSupported(mParameters, "contrast") &&
+ !CameraUtil.isSupported(mParameters, "max-contrast")) {
+ removePreference(group, contrast.getKey());
+ }
+
+ if (sharpness != null && !CameraUtil.isSupported(mParameters, "sharpness") &&
+ !CameraUtil.isSupported(mParameters, "max-sharpness")) {
+ removePreference(group, sharpness.getKey());
+ }
+
if (mIso != null) {
filterUnsupportedOptions(group,
- mIso, ParametersWrapper.getSupportedIsoValues(mParameters));
+ mIso, getSupportedIsoValues(mParameters));
+ }
+
+ if (mShutterSpeed != null) {
+ filterUnsupportedOptions(group,
+ mShutterSpeed, getSupportedShutterSpeedValues(mParameters));
}
if (redeyeReduction != null) {
@@ -872,6 +990,11 @@ public class CameraSettings {
colorEffect, mParameters.getSupportedColorEffects());
}
+ if (camcorderColorEffect != null) {
+ filterUnsupportedOptions(group,
+ camcorderColorEffect, mParameters.getSupportedColorEffects());
+ }
+
if (aeBracketing != null) {
filterUnsupportedOptions(group,
aeBracketing, getSupportedAEBracketingModes(mParameters));
@@ -887,14 +1010,24 @@ public class CameraSettings {
faceRC, getSupportedFaceRecognitionModes(mParameters));
}
+ if (faceDetection != null) {
+ filterUnsupportedOptions(group,
+ faceDetection, getSupportedFaceDetection(mParameters));
+ }
+
if (autoExposure != null) {
filterUnsupportedOptions(group,
autoExposure, ParametersWrapper.getSupportedAutoexposure(mParameters));
}
- if(videoSnapSize != null) {
- filterUnsupportedOptions(group, videoSnapSize, getSupportedVideoSnapSizes(mParameters));
- filterSimilarPictureSize(group, videoSnapSize);
+ if (videoSnapSize != null) {
+ if (CameraUtil.isVideoSnapshotSupported(mParameters)) {
+ filterUnsupportedOptions(group, videoSnapSize,
+ getSupportedVideoSnapSizes(mParameters));
+ filterSimilarPictureSize(group, videoSnapSize);
+ } else {
+ removePreference(group, videoSnapSize.getKey());
+ }
}
if (histogram!= null) {
@@ -915,6 +1048,10 @@ public class CameraSettings {
removePreference(group, longShot.getKey());
}
+ if (auto_hdr != null && !CameraUtil.isAutoHDRSupported(mParameters)) {
+ removePreference(group, auto_hdr.getKey());
+ }
+
if (videoRotation != null) {
filterUnsupportedOptions(group,
videoRotation, ParametersWrapper.getSupportedVideoRotationValues(mParameters));
@@ -960,6 +1097,7 @@ public class CameraSettings {
ListPreference sceneMode = group.findPreference(KEY_SCENE_MODE);
ListPreference flashMode = group.findPreference(KEY_FLASH_MODE);
ListPreference focusMode = group.findPreference(KEY_FOCUS_MODE);
+ ListPreference videoFocusMode = group.findPreference(KEY_VIDEOCAMERA_FOCUS_MODE);
IconListPreference exposure =
(IconListPreference) group.findPreference(KEY_EXPOSURE);
IconListPreference cameraIdPref =
@@ -970,11 +1108,13 @@ public class CameraSettings {
ListPreference cameraHdr = group.findPreference(KEY_CAMERA_HDR);
ListPreference disMode = group.findPreference(KEY_DIS);
ListPreference cameraHdrPlus = group.findPreference(KEY_CAMERA_HDR_PLUS);
+ ListPreference powerShutter = group.findPreference(KEY_POWER_SHUTTER);
ListPreference videoHfrMode =
group.findPreference(KEY_VIDEO_HIGH_FRAME_RATE);
ListPreference seeMoreMode = group.findPreference(KEY_SEE_MORE);
ListPreference videoEncoder = group.findPreference(KEY_VIDEO_ENCODER);
ListPreference noiseReductionMode = group.findPreference(KEY_NOISE_REDUCTION);
+ ListPreference savePath = group.findPreference(KEY_CAMERA_SAVEPATH);
// Since the screen could be loaded from different resources, we need
// to check if the preference is available here
@@ -989,9 +1129,9 @@ public class CameraSettings {
getSupportedSeeMoreModes(mParameters));
}
- if ((videoHfrMode != null) &&
- (ParametersWrapper.getSupportedHfrSizes(mParameters) == null)) {
- filterUnsupportedOptions(group, videoHfrMode, null);
+ if (videoHfrMode != null) {
+ filterUnsupportedOptions(group, videoHfrMode, getSupportedHighFrameRateModes(
+ mParameters));
}
if (videoQuality != null) {
@@ -1004,10 +1144,12 @@ public class CameraSettings {
}
if (pictureSize != null) {
- filterUnsupportedOptions(group, pictureSize, sizeListToStringList(
- mParameters.getSupportedPictureSizes()));
- filterSimilarPictureSize(group, pictureSize);
+ formatPictureSizes(pictureSize,
+ fromLegacySizes(mParameters.getSupportedPictureSizes()), mContext);
+ resetIfInvalid(pictureSize);
+
}
+
if (whiteBalance != null) {
filterUnsupportedOptions(group,
whiteBalance, mParameters.getSupportedWhiteBalance());
@@ -1016,7 +1158,7 @@ public class CameraSettings {
if (chromaFlash != null) {
List<String> supportedAdvancedFeatures =
getSupportedAdvancedFeatures(mParameters);
- if (!CameraUtil.isSupported(
+ if (hasChromaFlashScene(mContext) || !CameraUtil.isSupported(
mContext.getString(R.string
.pref_camera_advanced_feature_value_chromaflash_on),
supportedAdvancedFeatures)) {
@@ -1044,6 +1186,13 @@ public class CameraSettings {
supportedSceneModes.add(mContext.getString(R.string
.pref_camera_advanced_feature_value_optizoom_on));
}
+ if (hasChromaFlashScene(mContext) && CameraUtil.isSupported(
+ mContext.getString(R.string
+ .pref_camera_advanced_feature_value_chromaflash_on),
+ supportedAdvancedFeatures)) {
+ supportedSceneModes.add(mContext.getString(R.string
+ .pref_camera_advanced_feature_value_chromaflash_on));
+ }
filterUnsupportedOptions(group, sceneMode, supportedSceneModes);
}
if (flashMode != null) {
@@ -1055,10 +1204,12 @@ public class CameraSettings {
disMode, getSupportedDISModes(mParameters));
}
if (focusMode != null) {
- if (!CameraUtil.isFocusAreaSupported(mParameters)) {
- filterUnsupportedOptions(group,
- focusMode, mParameters.getSupportedFocusModes());
- }
+ filterUnsupportedOptions(group,
+ focusMode, mParameters.getSupportedFocusModes());
+ }
+ if (videoFocusMode != null) {
+ filterUnsupportedOptions(group,
+ videoFocusMode, mParameters.getSupportedFocusModes());
}
if (videoFlashMode != null) {
filterUnsupportedOptions(group,
@@ -1083,12 +1234,15 @@ public class CameraSettings {
!GcamHelper.hasGcamCapture() || isFrontCamera)) {
removePreference(group, cameraHdrPlus.getKey());
}
+ if (powerShutter != null && CameraUtil.hasCameraKey()) {
+ removePreference(group, powerShutter.getKey());
+ }
if (PersistUtil.isSaveInSdEnabled()) {
final String CAMERA_SAVEPATH_SDCARD = "1";
final int CAMERA_SAVEPATH_SDCARD_IDX = 1;
final int CAMERA_SAVEPATH_PHONE_IDX = 0;
- ListPreference savePath = group.findPreference(KEY_CAMERA_SAVEPATH);
+
SharedPreferences pref = group.getSharedPreferences();
String savePathValue = null;
if (pref != null) {
@@ -1104,7 +1258,13 @@ public class CameraSettings {
Log.d(TAG, "set Phone as save path when sdCard is unavailable.");
savePath.setValueIndex(CAMERA_SAVEPATH_PHONE_IDX);
}
- }
+ }
+ }
+ if (savePath != null) {
+ Log.d(TAG, "check storage menu " + SDCard.instance().isWriteable());
+ if (!SDCard.instance().isWriteable()) {
+ removePreference(group, savePath.getKey());
+ }
}
qcomInitPreferences(group);
@@ -1152,9 +1312,11 @@ public class CameraSettings {
return;
}
-// if (numOfCameras > 2 ) {
-// numOfCameras = 2;
-// }
+ if (!mSupportBokehMode) {
+ if (numOfCameras > 2) {
+ numOfCameras = 2;
+ }
+ }
CharSequence[] entryValues = new CharSequence[numOfCameras];
for (int i = 0; i < numOfCameras; ++i) {
@@ -1211,7 +1373,7 @@ public class CameraSettings {
return false;
}
- private static void resetIfInvalid(ListPreference pref) {
+ static void resetIfInvalid(ListPreference pref) {
// Set the value to the first entry if it is invalid.
String value = pref.getValue();
if (pref.findIndexOfValue(value) == NOT_FOUND) {
@@ -1280,17 +1442,20 @@ public class CameraSettings {
version = 2;
}
if (version == 2) {
- editor.putString(KEY_RECORD_LOCATION,
- pref.getBoolean(KEY_RECORD_LOCATION, false)
- ? RecordLocationPreference.VALUE_ON
- : RecordLocationPreference.VALUE_NONE);
+ try {
+ boolean value = pref.getBoolean(KEY_RECORD_LOCATION, false);
+ editor.putString(KEY_RECORD_LOCATION,
+ value ? RecordLocationPreference.VALUE_ON
+ : RecordLocationPreference.VALUE_NONE);
+ } catch (ClassCastException e) {
+ Log.e(TAG, "error convert record location", e);
+ }
version = 3;
}
if (version == 3) {
// Just use video quality to replace it and
// ignore the current settings.
editor.remove("pref_camera_videoquality_key");
- editor.remove("pref_camera_video_duration_key");
}
editor.putInt(KEY_VERSION, CURRENT_VERSION);
@@ -1370,124 +1535,61 @@ public class CameraSettings {
initialCameraPictureSize(context, parameters);
writePreferredCameraId(preferences, currentCameraId);
}
- private static boolean checkSupportedVideoQuality(Parameters parameters,int width, int height){
- List <Size> supported = parameters.getSupportedVideoSizes();
- int flag = 0;
- for (Size size : supported){
- //since we are having two profiles with same height, we are checking with height
- if (size.height == 480) {
- if (size.height == height && size.width == width) {
- flag = 1;
- break;
- }
- } else {
- if (size.width == width) {
- flag = 1;
- break;
- }
- }
- }
- if (flag == 1)
- return true;
- return false;
- }
- private static ArrayList<String> getSupportedVideoQuality(int cameraId,Parameters parameters) {
+ public static List<String> getSupportedHighFrameRateModes(Parameters params) {
ArrayList<String> supported = new ArrayList<String>();
- // Check for supported quality
- if (ApiHelper.HAS_FINE_RESOLUTION_QUALITY_LEVELS) {
- getFineResolutionQuality(supported,cameraId,parameters);
- } else {
- supported.add(Integer.toString(CamcorderProfile.QUALITY_HIGH));
- CamcorderProfile high = CamcorderProfile.get(
- cameraId, CamcorderProfile.QUALITY_HIGH);
- CamcorderProfile low = CamcorderProfile.get(
- cameraId, CamcorderProfile.QUALITY_LOW);
- if (high.videoFrameHeight * high.videoFrameWidth >
- low.videoFrameHeight * low.videoFrameWidth) {
- supported.add(Integer.toString(CamcorderProfile.QUALITY_LOW));
- }
- }
-
- return supported;
- }
-
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
- private static void getFineResolutionQuality(ArrayList<String> supported,
- int cameraId,Parameters parameters) {
-
- if (CamcorderProfile.hasProfile(cameraId, CamcorderProfileWrapper.QUALITY_4KDCI)) {
- if (checkSupportedVideoQuality(parameters,4096,2160)) {
- supported.add(Integer.toString(CamcorderProfileWrapper.QUALITY_4KDCI));
- }
- }
+ List<String> supportedModes = params.getSupportedVideoHighFrameRateModes();
+ String hsr = params.get(KEY_VIDEO_HSR);
- if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_2160P)) {
- if (checkSupportedVideoQuality(parameters,3840,2160)) {
- supported.add(Integer.toString(CamcorderProfile.QUALITY_2160P));
- }
- }
- if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_1080P)) {
- if (checkSupportedVideoQuality(parameters,1920,1080)){
- supported.add(Integer.toString(CamcorderProfile.QUALITY_1080P));
- }
- }
- if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_720P)) {
- if (checkSupportedVideoQuality(parameters,1280,720)){
- supported.add(Integer.toString(CamcorderProfile.QUALITY_720P));
- }
- }
- if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_480P)) {
- if (checkSupportedVideoQuality(parameters,720,480)){
- supported.add(Integer.toString(CamcorderProfile.QUALITY_480P));
- }
- }
-
- if (CamcorderProfile.hasProfile(cameraId, CamcorderProfileWrapper.QUALITY_VGA)) {
- if (checkSupportedVideoQuality(parameters,640,480)){
- supported.add(Integer.toString(CamcorderProfileWrapper.QUALITY_VGA));
- }
+ if (supportedModes == null) {
+ return null;
}
- if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_CIF)) {
- if (checkSupportedVideoQuality(parameters,352,288)){
- supported.add(Integer.toString(CamcorderProfile.QUALITY_CIF));
- }
- }
- if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_QVGA)) {
- if (checkSupportedVideoQuality(parameters,320,240)){
- supported.add(Integer.toString(CamcorderProfile.QUALITY_QVGA));
- }
- }
- if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_QCIF)) {
- if (checkSupportedVideoQuality(parameters,176,144)){
- supported.add(Integer.toString(CamcorderProfile.QUALITY_QCIF));
- }
+ for (String highFrameRateMode : supportedModes) {
+ if (highFrameRateMode.equals("off")) {
+ supported.add(highFrameRateMode);
+ } else {
+ supported.add("hfr" + highFrameRateMode);
+ if (hsr != null) {
+ supported.add("hsr" + highFrameRateMode);
+ }
+ }
}
-
+ return supported;
}
- public static ArrayList<String> getSupportedVideoQualities(int cameraId,Parameters parameters) {
+ public static ArrayList<String> getSupportedVideoQualities(int cameraId,
+ Parameters parameters) {
ArrayList<String> supported = new ArrayList<String>();
- List<String> temp = sizeListToStringList(parameters.getSupportedVideoSizes());
+ List<Size> supportedVideoSizes = parameters.getSupportedVideoSizes();
+ List<String> temp;
+ if (supportedVideoSizes == null) {
+ // video-size not specified in parameter list,
+ // assume all profiles in media_profiles are supported.
+ temp = new ArrayList<String>();
+ temp.add("4096x2160");
+ temp.add("3840x2160");
+ temp.add("1920x1080");
+ temp.add("1280x720");
+ temp.add("720x480");
+ temp.add("640x480");
+ temp.add("352x288");
+ temp.add("320x240");
+ temp.add("176x144");
+ } else {
+ temp = sizeListToStringList(supportedVideoSizes);
+ }
+
for (String videoSize : temp) {
if (VIDEO_QUALITY_TABLE.containsKey(videoSize)) {
int profile = VIDEO_QUALITY_TABLE.get(videoSize);
if (CamcorderProfile.hasProfile(cameraId, profile)) {
- supported.add(videoSize);
+ supported.add(videoSize);
}
}
}
return supported;
}
- public static int getVideoDurationInMillis(String quality) {
- if (VIDEO_QUALITY_MMS.equals(quality)) {
- return MMS_VIDEO_DURATION * 1000;
- } else if (VIDEO_QUALITY_YOUTUBE.equals(quality)) {
- return YOUTUBE_VIDEO_DURATION * 1000;
- }
- return DEFAULT_VIDEO_DURATION * 1000;
- }
public static boolean isInternalPreviewSupported(Parameters params) {
boolean ret = false;
@@ -1559,6 +1661,11 @@ public class CameraSettings {
public static boolean isBokehModeSupported(Parameters params) {
boolean ret = false;
+
+ if (!mSupportBokehMode) {
+ return ret;
+ }
+
if (null != params) {
String val = params.get(KEY_QC_IS_BOKEH_MODE_SUPPORTED);
if ("1".equals(val)) {
@@ -1570,6 +1677,11 @@ public class CameraSettings {
public static boolean isBokehMPOSupported(Parameters params) {
boolean ret = false;
+
+ if (!mSupportBokehMode) {
+ return ret;
+ }
+
if (null != params) {
String val = params.get(KEY_QC_IS_BOKEH_MPO_SUPPORTED);
if ("1".equals(val)) {
@@ -1587,4 +1699,185 @@ public class CameraSettings {
Log.d(TAG,"getSupportedDegreesOfBlur str =" +str);
return split(str);
}
+
+ // common aspect ratios used for bucketing camera picture sizes
+ private enum AspectRatio {
+ FourThree(1.27, 1.42, R.string.pref_camera_aspectratio_43),
+ ThreeTwo(1.42, 1.55, R.string.pref_camera_aspectratio_32),
+ SixteenTen(1.55, 1.63, R.string.pref_camera_aspectratio_1610),
+ FiveThree(1.63, 1.73, R.string.pref_camera_aspectratio_53),
+ SixteenNine(1.73, 1.81, R.string.pref_camera_aspectratio_169),
+ OneOne(0.95, 1.05, R.string.pref_camera_aspectratio_11),
+ Wide(1.81, Float.MAX_VALUE, R.string.pref_camera_aspectratio_wide),
+ Other(Float.MIN_VALUE, 1.27, 0);
+
+ public double min;
+ public double max;
+ public int resourceId;
+
+ AspectRatio(double min, double max, int rid) {
+ this.min = min;
+ this.max = max;
+ this.resourceId = rid;
+ }
+
+ boolean contains(double ratio) {
+ return (ratio >= min) && (ratio < max);
+ }
+
+ static AspectRatio of(int width, int height) {
+ double ratio = ((double) width) / height;
+ for (AspectRatio aspect : values()) {
+ if (aspect.contains(ratio)) { return aspect; }
+ }
+ return null;
+ }
+ }
+
+ // track a camera picture size along with some derived info
+ private static class SizeEntry implements Comparable<SizeEntry> {
+ AspectRatio ratio;
+ android.util.Size size;
+ int pixels;
+
+ SizeEntry(android.util.Size size) {
+ this.ratio = AspectRatio.of(size.getWidth(), size.getHeight());
+ this.size = size;
+ this.pixels = size.getWidth() * size.getHeight();
+ }
+
+ @Override
+ public int compareTo(SizeEntry another) {
+ return another.pixels - pixels;
+ }
+
+ String resolution() { return size.getWidth()+"x"+size.getHeight(); }
+
+ String formatted(Context ctx) {
+ double pixelCount = pixels / 1000000d; // compute megapixels
+
+ if (pixelCount > 1.9 && pixelCount < 2.0) { //conventional rounding
+ pixelCount = 2.0;
+ }
+
+ pixelCount = adjustForLocale(pixelCount); // some locales group differently
+
+ if (pixelCount > 0.1) {
+ String ratioString = ratio.resourceId == 0
+ ? resolution() : ctx.getString(ratio.resourceId);
+ return ctx.getString(R.string.pref_camera_megapixel_format,
+ ratioString, pixelCount);
+ } else {
+ // for super tiny stuff, just give the raw resolution
+ return resolution();
+ }
+ }
+
+ private static final String KOREAN = Locale.KOREAN.getLanguage();
+ private static final String CHINESE = Locale.CHINESE.getLanguage();
+
+ private double adjustForLocale(double megapixels) {
+ Locale locale = Locale.getDefault();
+ if (locale == null) { return megapixels; }
+ String language = locale.getLanguage();
+ // chinese and korean locales prefer to count by ten thousands
+ // instead of by millions - so we multiply the megapixels by 100
+ // (with a little rounding on the way)
+ if (KOREAN.equals(language) || CHINESE.equals(language)) {
+ megapixels = Math.round(megapixels * 10);
+ return megapixels * 10; // wàn
+ }
+ return megapixels;
+ }
+ }
+
+ static List<android.util.Size> fromLegacySizes(List<Size> oldSizes) {
+ final List<android.util.Size> sizes = new ArrayList<>();
+ if (oldSizes == null || oldSizes.size() == 0) {
+ return sizes;
+ }
+ for (Size oldSize : oldSizes) {
+ sizes.add(new android.util.Size(oldSize.width, oldSize.height));
+ }
+ return sizes;
+ }
+
+ static void formatPictureSizes(
+ ListPreference pictureSize, List<android.util.Size> supported, Context ctx) {
+ if (supported == null || supported.isEmpty()) { return; }
+
+ // convert list of sizes to list of "size entries"
+ List<SizeEntry> sizes = new ArrayList<SizeEntry>(supported.size());
+ for (android.util.Size candidate : supported) { sizes.add(new SizeEntry(candidate)); }
+
+ // sort descending by pixel size
+ Collections.sort(sizes);
+
+ // trim really small sizes but never leave less than six choices
+ int minimum = ctx.getResources().getInteger(R.integer.minimum_picture_size);
+ while (sizes.size() > 6) {
+ int lastIndex = sizes.size() - 1;
+ SizeEntry last = sizes.get(lastIndex);
+ if (last.pixels < minimum) { sizes.remove(lastIndex); }
+ else { break; }
+ }
+ // re-sort into aspect ratio buckets
+ MultiMap<AspectRatio,SizeEntry> buckets = new MultiMap<AspectRatio,SizeEntry>();
+ for (SizeEntry size : sizes) { buckets.put(size.ratio, size); }
+
+ // build the final lists - group by aspect ratio, with those
+ // buckets having the largest image sizes positioned first
+ List<String> entries = new ArrayList<String>(buckets.size());
+ List<String> entryValues = new ArrayList<String>(buckets.size());
+ while (!buckets.isEmpty()) {
+ // find the bucket with the largest first element
+ int maxSize = 0;
+ AspectRatio chosenKey = null;
+ for (AspectRatio ratio : buckets.keySet()) {
+ int size = buckets.get(ratio).get(0).pixels;
+ if (size > maxSize) {
+ maxSize = size;
+ chosenKey = ratio;
+ }
+ }
+
+ List<SizeEntry> bucket = buckets.remove(chosenKey);
+
+ // trim chosen bucket of similarly sized entries, but
+ // never leave less that three
+ int index = 0;
+ while (bucket.size() > 3 && bucket.size() > index + 1) {
+ SizeEntry current = bucket.get(index);
+ SizeEntry next = bucket.get(index + 1);
+ // if the two buckets differ in size by less than 30%
+ // remove the smaller one, otherwise advance through the list
+ if (((double) current.pixels) / next.pixels < 1.3) {
+ bucket.remove(index + 1);
+ } else {
+ index++;
+ }
+ }
+
+ // transfer chosen, trimmed bucket to final list
+ for (SizeEntry size : bucket) {
+ entryValues.add(size.resolution());
+ entries.add(size.formatted(ctx));
+ }
+ }
+
+ pictureSize.setEntries(entries.toArray(new String[entries.size()]));
+ pictureSize.setEntryValues(entryValues.toArray(new String[entryValues.size()]));
+ }
+
+ public static boolean hasChromaFlashScene(Context context) {
+ String[] sceneModes = context.getResources().getStringArray(
+ R.array.pref_camera_scenemode_entryvalues);
+ for (String mode : sceneModes) {
+ if (mode.equals(context.getResources().getString(R.string
+ .pref_camera_advanced_feature_value_chromaflash_on))) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index a55c9e451..6f6a32a80 100755
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -114,6 +114,7 @@ import com.android.camera.imageprocessor.filter.SharpshooterFilter;
import com.android.camera.imageprocessor.filter.StillmoreFilter;
import com.android.camera.imageprocessor.filter.UbifocusFilter;
import com.android.camera.ui.CountDownView;
+import com.android.camera.ui.focus.FocusRing;
import com.android.camera.ui.ModuleSwitcher;
import com.android.camera.ui.ProMode;
import com.android.camera.ui.RotateTextToast;
@@ -412,7 +413,7 @@ public class CaptureModule implements CameraModule, PhotoController,
private float mZoomValue = 1f;
private FocusStateListener mFocusStateListener;
private LocationManager mLocationManager;
- private SettingsManager mSettingsManager;
+ public SettingsManager mSettingsManager;
private long SECONDARY_SERVER_MEM;
private boolean mLongshotActive = false;
private CameraCharacteristics mMainCameraCharacteristics;
@@ -684,7 +685,12 @@ public class CaptureModule implements CameraModule, PhotoController,
private void detectHDRMode(CaptureResult result, int id) {
String value = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
String autoHdr = mSettingsManager.getValue(SettingsManager.KEY_AUTO_HDR);
- Byte hdrScene = result.get(CaptureModule.isHdr);
+ Byte hdrScene = null;
+ try {
+ hdrScene = result.get(CaptureModule.isHdr);
+ } catch (IllegalArgumentException e) {
+ // Ignore exception.
+ }
if (value == null || hdrScene == null) return;
mAutoHdrEnable = false;
if (autoHdr != null && "enable".equals(autoHdr) && "0".equals(value) && hdrScene == 1) {
@@ -767,7 +773,12 @@ public class CaptureModule implements CameraModule, PhotoController,
}
}
if (SettingsManager.getInstance().isStatsVisualizerSupport() == 3) {
- int[] histogramStats = result.get(CaptureModule.histogramStats);
+ int[] histogramStats = null;
+ try {
+ histogramStats = result.get(CaptureModule.histogramStats);
+ } catch (IllegalArgumentException e) {
+ // Ignore exception.
+ }
if (histogramStats != null && mHiston) {
/*The first element in the array stores max hist value . Stats data begin
from second value*/
@@ -2168,12 +2179,6 @@ public class CaptureModule implements CameraModule, PhotoController,
Log.d(TAG, "captureStillPictureForLongshot onCaptureCompleted: " + id);
if (mLongshotActive) {
checkAndPlayShutterSound(id);
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mUI.doShutterAnimation();
- }
- });
}
}
@@ -2182,14 +2187,6 @@ public class CaptureModule implements CameraModule, PhotoController,
CaptureRequest request,
CaptureFailure result) {
Log.d(TAG, "captureStillPictureForLongshot onCaptureFailed: " + id);
- if (mLongshotActive) {
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mUI.doShutterAnimation();
- }
- });
- }
}
@Override
@@ -2345,12 +2342,24 @@ public class CaptureModule implements CameraModule, PhotoController,
* @param width The width of available size for camera preview
* @param height The height of available size for camera preview
*/
- private void setUpCameraOutputs(int imageFormat) {
+ private void setUpCameraOutputs(boolean isFilterOrZslEnabled) {
+ int imageFormat = ImageFormat.JPEG;
+
Log.d(TAG, "setUpCameraOutputs");
CameraManager manager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
try {
String[] cameraIdList = manager.getCameraIdList();
- for (int i = 0; i < cameraIdList.length; i++) {
+ int cameraIdListLength = cameraIdList.length;
+
+ if (cameraIdListLength > MAX_NUM_CAM)
+ Log.w(TAG, "Number of available cameras (" + cameraIdListLength + ") exceeds "
+ + "max supported cameras (" + MAX_NUM_CAM + ")");
+
+ for (int i = 0; i < cameraIdListLength; i++) {
+ if (i >= MAX_NUM_CAM) {
+ Log.w(TAG, "Skipping set up for camera with id " + i);
+ break;
+ }
String cameraId = cameraIdList[i];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
@@ -2382,6 +2391,23 @@ public class CaptureModule implements CameraModule, PhotoController,
}
mCameraId[i] = cameraId;
+ // Set ImageFormat for ZSL
+ if (isFilterOrZslEnabled) {
+ for (int capability : capabilities) {
+ // YUV has higher priority
+ if (capability == CameraCharacteristics
+ .REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING) {
+ Log.d(TAG, "ImageFormat: YUV_420_888");
+ imageFormat = ImageFormat.YUV_420_888;
+ break;
+ } else if (capability == CameraCharacteristics
+ .REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING) {
+ Log.d(TAG, "ImageFormat: PRIVATE");
+ imageFormat = ImageFormat.PRIVATE;
+ }
+ }
+ }
+
if (isClearSightOn()) {
if(i == getMainCameraId()) {
// ClearSightImageProcessor.getInstance().init(map, mPictureSize.getWidth(),
@@ -2543,7 +2569,7 @@ public class CaptureModule implements CameraModule, PhotoController,
@Override
public void run() {
if (mUI.getCurrentProMode() != ProMode.MANUAL_MODE)
- mUI.clearFocus();
+ mUI.getFocusRing().stopFocusAnimations();
}
});
}
@@ -3120,15 +3146,12 @@ public class CaptureModule implements CameraModule, PhotoController,
mFrameProcessor.onOpen(getFrameProcFilterId(), mPreviewSize);
}
- if(mPostProcessor.isZSLEnabled()) {
- mChosenImageFormat = ImageFormat.PRIVATE;
- } else if(mPostProcessor.isFilterOn() || getFrameFilters().size() != 0 || mPostProcessor.isSelfieMirrorOn()) {
- mChosenImageFormat = ImageFormat.YUV_420_888;
+ if (mPostProcessor.isFilterOn() || getFrameFilters().size() != 0 ||
+ mPostProcessor.isSelfieMirrorOn()) {
+ setUpCameraOutputs(true);
} else {
- mChosenImageFormat = ImageFormat.JPEG;
+ setUpCameraOutputs(false);
}
- setUpCameraOutputs(mChosenImageFormat);
-
}
@Override
@@ -3150,27 +3173,10 @@ public class CaptureModule implements CameraModule, PhotoController,
openProcessors();
Message msg = Message.obtain();
msg.what = OPEN_CAMERA;
- if (isBackCamera()) {
- switch (getCameraMode()) {
- case DUAL_MODE:
- case BAYER_MODE:
- msg.arg1 = BAYER_ID;
- mCameraHandler.sendMessage(msg);
- break;
- case MONO_MODE:
- msg.arg1 = MONO_ID;
- mCameraHandler.sendMessage(msg);
- break;
- case SWITCH_MODE:
- msg.arg1 = SWITCH_ID;
- mCameraHandler.sendMessage(msg);
- break;
- }
- } else {
- int cameraId = SWITCH_ID == -1? FRONT_ID : SWITCH_ID;
- msg.arg1 = cameraId;
- mCameraHandler.sendMessage(msg);
- }
+ int cameraId = getMainCameraId();
+ msg.arg1 = cameraId;
+ mCameraHandler.sendMessage(msg);
+
if (mDeepPortraitMode) {
mUI.startDeepPortraitMode(mPreviewSize);
if (mUI.getGLCameraPreview() != null) {
@@ -3253,9 +3259,6 @@ public class CaptureModule implements CameraModule, PhotoController,
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
- if (CameraUtil.volumeKeyShutterDisable(mActivity)) {
- return false;
- }
case KeyEvent.KEYCODE_FOCUS:
if (mFirstTimeInitialized) {
if (event.getRepeatCount() == 0) {
@@ -3288,8 +3291,7 @@ public class CaptureModule implements CameraModule, PhotoController,
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
- if (mFirstTimeInitialized
- && !CameraUtil.volumeKeyShutterDisable(mActivity)) {
+ if (mFirstTimeInitialized) {
onShutterButtonClick();
return true;
}
@@ -3478,10 +3480,10 @@ public class CaptureModule implements CameraModule, PhotoController,
int[] newXY = {x, y};
if (mUI.isOverControlRegion(newXY)) return;
if (!mUI.isOverSurfaceView(newXY)) return;
- mUI.setFocusPosition(x, y);
+ mUI.getFocusRing().startActiveFocus();
+ mUI.getFocusRing().setFocusLocation(x, y);
x = newXY[0];
y = newXY[1];
- mUI.onFocusStarted();
if (isBackCamera()) {
switch (getCameraMode()) {
case DUAL_MODE:
@@ -3795,7 +3797,9 @@ public class CaptureModule implements CameraModule, PhotoController,
mSupportedMaxPictureSize = prevSizes[0];
Size[] rawSize = mSettingsManager.getSupportedOutputSize(getMainCameraId(),
ImageFormat.RAW10);
- mSupportedRawPictureSize = rawSize[0];
+ if (rawSize != null && rawSize.length > 0) {
+ mSupportedRawPictureSize = rawSize[0];
+ }
mPreviewSize = getOptimalPreviewSize(mPictureSize, prevSizes);
Size[] thumbSizes = mSettingsManager.getSupportedThumbnailSizes(getMainCameraId());
mPictureThumbSize = getOptimalPreviewSize(mPictureSize, thumbSizes); // get largest thumb size
@@ -3880,6 +3884,10 @@ public class CaptureModule implements CameraModule, PhotoController,
private void updateMaxVideoDuration() {
String minutesStr = mSettingsManager.getValue(SettingsManager.KEY_VIDEO_DURATION);
+ if (minutesStr == null) {
+ mMaxVideoDurationInMs = 0;
+ return;
+ }
int minutes = Integer.parseInt(minutesStr);
if (minutes == -1) {
// User wants lowest, set 30s */
@@ -3957,7 +3965,7 @@ public class CaptureModule implements CameraModule, PhotoController,
return;
}
- mUI.clearFocus();
+ mUI.getFocusRing().stopFocusAnimations();
mUI.resetPauseButton();
mRecordingTotalTime = 0L;
mRecordingStartTime = SystemClock.uptimeMillis();
@@ -4009,7 +4017,7 @@ public class CaptureModule implements CameraModule, PhotoController,
mHandler.post(new Runnable() {
@Override
public void run() {
- mUI.clearFocus();
+ mUI.getFocusRing().stopFocusAnimations();
mUI.resetPauseButton();
mRecordingTotalTime = 0L;
mRecordingStartTime = SystemClock.uptimeMillis();
@@ -4143,7 +4151,7 @@ public class CaptureModule implements CameraModule, PhotoController,
try {
setUpMediaRecorder(cameraId);
- mUI.clearFocus();
+ mUI.getFocusRing().stopFocusAnimations();
mUI.hideUIwhileRecording();
mCameraHandler.removeMessages(CANCEL_TOUCH_FOCUS, mCameraId[cameraId]);
mState[cameraId] = STATE_PREVIEW;
@@ -4238,7 +4246,7 @@ public class CaptureModule implements CameraModule, PhotoController,
restartSession(true);
return;
}
- mUI.clearFocus();
+ mUI.getFocusRing().stopFocusAnimations();
mUI.resetPauseButton();
mRecordingTotalTime = 0L;
mRecordingStartTime = SystemClock.uptimeMillis();
@@ -5256,6 +5264,8 @@ public class CaptureModule implements CameraModule, PhotoController,
}
private void applyInstantAEC(CaptureRequest.Builder request) {
+ if (!VendorTagUtil.isSupported(request, CaptureModule.INSTANT_AEC_MODE))
+ return;
String value = mSettingsManager.getValue(SettingsManager.KEY_INSTANT_AEC);
if (value == null || value.equals("0"))
return;
@@ -5264,6 +5274,8 @@ public class CaptureModule implements CameraModule, PhotoController,
}
private void applySaturationLevel(CaptureRequest.Builder request) {
+ if (!VendorTagUtil.isSupported(request, CaptureModule.SATURATION))
+ return;
String value = mSettingsManager.getValue(SettingsManager.KEY_SATURATION_LEVEL);
if (value != null) {
int intValue = Integer.parseInt(value);
@@ -5340,6 +5352,8 @@ public class CaptureModule implements CameraModule, PhotoController,
}
private void applyExposureMeteringModes(CaptureRequest.Builder request) {
+ if (!VendorTagUtil.isSupported(request, CaptureModule.exposure_metering))
+ return;
String value = mSettingsManager.getValue(SettingsManager.KEY_EXPOSURE_METERING_MODE);
if (value != null) {
int intValue = Integer.parseInt(value);
@@ -5348,6 +5362,8 @@ public class CaptureModule implements CameraModule, PhotoController,
}
private void applyHistogram(CaptureRequest.Builder request) {
+ if (!VendorTagUtil.isSupported(request, CaptureModule.histMode))
+ return;
String value = mSettingsManager.getValue(SettingsManager.KEY_STATS_VISUALIZER_VALUE);
if (value != null ) {
if (value.equals("3")) {
diff --git a/src/com/android/camera/CaptureUI.java b/src/com/android/camera/CaptureUI.java
index ccb45e12d..12b7480d5 100755
--- a/src/com/android/camera/CaptureUI.java
+++ b/src/com/android/camera/CaptureUI.java
@@ -71,11 +71,10 @@ import com.android.camera.imageprocessor.filter.DeepPortraitFilter;
import com.android.camera.ui.AutoFitSurfaceView;
import com.android.camera.ui.Camera2FaceView;
import com.android.camera.ui.CameraControls;
-import com.android.camera.ui.MenuHelp;
import com.android.camera.ui.OneUICameraControls;
import com.android.camera.ui.CountDownView;
import com.android.camera.ui.FlashToggleButton;
-import com.android.camera.ui.FocusIndicator;
+import com.android.camera.ui.focus.FocusRing;
import com.android.camera.ui.PieRenderer;
import com.android.camera.ui.ProMode;
import com.android.camera.ui.RenderOverlay;
@@ -94,8 +93,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
-public class CaptureUI implements FocusOverlayManager.FocusUI,
- PreviewGestures.SingleTapListener,
+public class CaptureUI implements PreviewGestures.SingleTapListener,
CameraManager.CameraFaceDetectionCallback,
SettingsManager.Listener,
PauseButton.OnPauseButtonListener {
@@ -107,6 +105,7 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
private static final int ANIMATION_DURATION = 300;
private static final int CLICK_THRESHOLD = 200;
private static final int AUTOMATIC_MODE = 0;
+ private final FocusRing mFocusRing;
private CameraActivity mActivity;
private View mRootView;
private View mPreviewCover;
@@ -180,7 +179,6 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
private FlashToggleButton mFlashButton;
private CountDownView mCountDownView;
private OneUICameraControls mCameraControls;
- private MenuHelp mMenuHelp;
private PieRenderer mPieRenderer;
private ZoomRenderer mZoomRenderer;
private Allocation mMonoDummyAllocation;
@@ -302,6 +300,8 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
mSurfaceHolderMono = mSurfaceViewMono.getHolder();
mSurfaceHolderMono.addCallback(callbackMono);
+ mFocusRing = (FocusRing) mRootView.findViewById(R.id.focus_ring);
+
mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay);
mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
mVideoButton = (ImageView) mRootView.findViewById(R.id.video_button);
@@ -553,7 +553,6 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
mActivity.setPreviewGestures(mGestures);
mRecordingTimeRect.setVisibility(View.GONE);
- showFirstTimeHelp();
}
protected void showCapturedImageForReview(byte[] jpegData, int orientation) {
@@ -716,13 +715,8 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
mVideoButton.setVisibility(View.VISIBLE);
}
mShutterButton.setOnShutterButtonListener(mModule);
- mShutterButton.setImageResource(R.drawable.one_ui_shutter_anim);
- mShutterButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- doShutterAnimation();
- }
- });
+ mShutterButton.setImageResource(R.drawable.btn_new_shutter);
+
mVideoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -769,7 +763,6 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
if (mPreviewLayout != null && mPreviewLayout.getVisibility() == View.VISIBLE) {
return;
}
- clearFocus();
removeFilterMenu(false);
Intent intent = new Intent(mActivity, SettingsActivity.class);
mActivity.startActivity(intent);
@@ -815,7 +808,6 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
mSceneModeSwitcher.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- clearFocus();
removeFilterMenu(false);
Intent intent = new Intent(mActivity, SceneModeActivity.class);
intent.putExtra(CameraUtil.KEY_IS_SECURE_CAMERA, mActivity.isSecureCamera());
@@ -872,7 +864,7 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
} else {
mFlashButton.setVisibility(View.VISIBLE);
mFlashButton.init(false);
- mVideoButton.setImageResource(R.drawable.video_capture);
+ mVideoButton.setImageResource(R.drawable.btn_new_shutter_video);
mRecordingTimeRect.setVisibility(View.GONE);
mMuteButton.setVisibility(View.INVISIBLE);
}
@@ -1010,7 +1002,6 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
}
}
-
public void resetTrackingFocus() {
if(mModule.isTrackingFocusSettingOn()) {
mTrackingFocusRenderer.setVisible(false);
@@ -1122,10 +1113,8 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
mSettingsManager.setValueIndex(SettingsManager
.KEY_COLOR_EFFECT, j);
for (View v1 : views) {
- v1.setBackground(null);
+ v1.setActivated(v1 == v);
}
- ImageView image = (ImageView) v.findViewById(R.id.image);
- image.setBackgroundColor(HIGHLIGHT_COLOR);
}
}
return true;
@@ -1133,10 +1122,8 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
});
views[j] = imageView;
- if (i == init)
- imageView.setBackgroundColor(HIGHLIGHT_COLOR);
+ imageView.setActivated(i == init);
TextView label = (TextView) filterBox.findViewById(R.id.label);
-
imageView.setImageResource(thumbnails[i]);
label.setText(entries[i]);
gridLayout.addView(filterBox);
@@ -1151,7 +1138,7 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
public void animateFadeIn(View v) {
ViewPropertyAnimator vp = v.animate();
- vp.alpha(0.85f).setDuration(ANIMATION_DURATION);
+ vp.alpha(1f).setDuration(ANIMATION_DURATION);
vp.start();
}
@@ -1284,17 +1271,10 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
}
}
- public void doShutterAnimation() {
- AnimationDrawable frameAnimation = (AnimationDrawable) mShutterButton.getDrawable();
- frameAnimation.stop();
- frameAnimation.start();
- }
-
public void showUI() {
if (!mUIhidden)
return;
mUIhidden = false;
- mPieRenderer.setBlockFocus(false);
mCameraControls.showUI();
}
@@ -1302,7 +1282,6 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
if (mUIhidden)
return;
mUIhidden = true;
- mPieRenderer.setBlockFocus(true);
mCameraControls.hideUI();
}
@@ -1540,74 +1519,8 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
mCameraControls.showRefocusToast(show);
}
- private FocusIndicator getFocusIndicator() {
- if (mModule.isTrackingFocusSettingOn()) {
- if (mPieRenderer != null) {
- mPieRenderer.clear();
- }
- return mTrackingFocusRenderer;
- }
- FocusIndicator focusIndicator;
- if (mFaceView != null && mFaceView.faceExists() && !mIsTouchAF) {
- if (mPieRenderer != null) {
- mPieRenderer.clear();
- }
- focusIndicator = mFaceView;
- } else {
- focusIndicator = mPieRenderer;
- }
-
- return focusIndicator;
- }
-
- @Override
- public boolean hasFaces() {
- return (mFaceView != null && mFaceView.faceExists());
- }
-
- public void clearFaces() {
- if (mFaceView != null) mFaceView.clear();
- }
-
- @Override
- public void clearFocus() {
- FocusIndicator indicator = getFocusIndicator();
- if (indicator != null) indicator.clear();
- mIsTouchAF = false;
- }
-
- @Override
- public void setFocusPosition(int x, int y) {
- mPieRenderer.setFocus(x, y);
- mIsTouchAF = true;
- }
-
- @Override
- public void onFocusStarted() {
- FocusIndicator indicator = getFocusIndicator();
- if (indicator != null) indicator.showStart();
- }
-
- @Override
- public void onFocusSucceeded(boolean timeout) {
- FocusIndicator indicator = getFocusIndicator();
- if (indicator != null) indicator.showSuccess(timeout);
- }
-
- @Override
- public void onFocusFailed(boolean timeOut) {
- FocusIndicator indicator = getFocusIndicator();
- if (indicator != null) indicator.showFail(timeOut);
-
- }
-
- @Override
- public void pauseFaceDetection() {
-
- }
-
- @Override
- public void resumeFaceDetection() {
+ public FocusRing getFocusRing() {
+ return mFocusRing;
}
public void onStartFaceDetection(int orientation, boolean mirror, Rect cameraBound,
@@ -1657,9 +1570,6 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
public void setOrientation(int orientation, boolean animation) {
mOrientation = orientation;
mCameraControls.setOrientation(orientation, animation);
- if (mMenuHelp != null) {
- mMenuHelp.setOrientation(orientation, animation);
- }
if (mFilterLayout != null) {
ViewGroup vg = (ViewGroup) mFilterLayout.getChildAt(0);
if (vg != null)
@@ -1716,33 +1626,6 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
return mOrientation;
}
- public void showFirstTimeHelp() {
- final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mActivity);
- boolean isMenuShown = prefs.getBoolean(CameraSettings.KEY_SHOW_MENU_HELP, false);
- if(!isMenuShown) {
- showFirstTimeHelp(mTopMargin, mBottomMargin);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putBoolean(CameraSettings.KEY_SHOW_MENU_HELP, true);
- editor.apply();
- }
- }
-
- private void showFirstTimeHelp(int topMargin, int bottomMargin) {
- mMenuHelp = (MenuHelp) mRootView.findViewById(R.id.menu_help);
- mMenuHelp.setForCamera2(true);
- mMenuHelp.setVisibility(View.VISIBLE);
- mMenuHelp.setMargins(topMargin, bottomMargin);
- mMenuHelp.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mMenuHelp != null) {
- mMenuHelp.setVisibility(View.GONE);
- mMenuHelp = null;
- }
- }
- });
- }
-
@Override
public void onSingleTapUp(View view, int x, int y) {
mModule.onSingleTapUp(view, x, y);
diff --git a/src/com/android/camera/ComboPreferences.java b/src/com/android/camera/ComboPreferences.java
index de6db8e9d..3ed11ba3a 100755
--- a/src/com/android/camera/ComboPreferences.java
+++ b/src/com/android/camera/ComboPreferences.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2013-2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -157,7 +158,9 @@ public class ComboPreferences implements
|| key.equals(SettingsManager.KEY_MONO_ONLY)
|| key.equals(SettingsManager.KEY_MONO_PREVIEW)
|| key.equals(SettingsManager.KEY_SWITCH_CAMERA)
- || key.equals(SettingsManager.KEY_CLEARSIGHT);
+ || key.equals(SettingsManager.KEY_CLEARSIGHT)
+ || key.equals(CameraSettings.KEY_POWER_SHUTTER)
+ || key.equals(CameraSettings.KEY_MAX_BRIGHTNESS);
}
@Override
diff --git a/src/com/android/camera/CountDownTimerPreference.java b/src/com/android/camera/CountDownTimerPreference.java
index 57820ac76..3d5f3a4c7 100644
--- a/src/com/android/camera/CountDownTimerPreference.java
+++ b/src/com/android/camera/CountDownTimerPreference.java
@@ -23,7 +23,7 @@ import org.codeaurora.snapcam.R;
public class CountDownTimerPreference extends IconListPreference {
private static final int[] DURATIONS = {
- 0, 2, 5, 10
+ 0, 1, 2, 3, 4, 5, 10, 15, 20, 30, 60
};
public CountDownTimerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -39,7 +39,7 @@ public class CountDownTimerPreference extends IconListPreference {
entries[0] = context.getString(R.string.setting_off); // Off
} else {
entries[i] = context.getResources()
- .getQuantityString(R.plurals.pref_camera_timer_entry, DURATIONS[i],
+ .getQuantityString(R.plurals.pref_camera_timer_entry, i,
DURATIONS[i]);
}
}
diff --git a/src/com/android/camera/DisableCameraReceiver.java b/src/com/android/camera/DisableCameraReceiver.java
index 4cef85f46..624874184 100644
--- a/src/com/android/camera/DisableCameraReceiver.java
+++ b/src/com/android/camera/DisableCameraReceiver.java
@@ -23,6 +23,8 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera.CameraInfo;
import android.util.Log;
+import com.android.camera.util.CameraUtil;
+import org.codeaurora.snapcam.R;
// We want to disable camera-related activities if there is no camera. This
// receiver runs when BOOT_COMPLETED intent is received. After running once
@@ -33,9 +35,21 @@ public class DisableCameraReceiver extends BroadcastReceiver {
private static final String ACTIVITIES[] = {
"com.android.camera.CameraLauncher",
};
+ private boolean mCamera2supported = false;
+ private boolean mCamera2enabled = false;
@Override
public void onReceive(Context context, Intent intent) {
+ // Check if the device supports Camera API 2
+ mCamera2supported = CameraUtil.isCamera2Supported(context);
+ Log.d(TAG, "Camera API 2 supported: " + mCamera2supported);
+
+ mCamera2enabled = mCamera2supported &&
+ context.getResources().getBoolean(R.bool.support_camera_api_v2);
+ Log.d(TAG, "Camera API 2 enabled: " + mCamera2enabled);
+
+ CameraHolder.setCamera2Mode(context, mCamera2enabled);
+
// Disable camera-related activities if there is no camera.
boolean needCameraActivity = CHECK_BACK_CAMERA_ONLY
? hasBackCamera()
@@ -53,23 +67,15 @@ public class DisableCameraReceiver extends BroadcastReceiver {
}
private boolean hasCamera() {
- int n = android.hardware.Camera.getNumberOfCameras();
+ int n = CameraHolder.instance().getNumberOfCameras();
Log.i(TAG, "number of camera: " + n);
return (n > 0);
}
private boolean hasBackCamera() {
- int n = android.hardware.Camera.getNumberOfCameras();
- CameraInfo info = new CameraInfo();
- for (int i = 0; i < n; i++) {
- android.hardware.Camera.getCameraInfo(i, info);
- if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
- Log.i(TAG, "back camera found: " + i);
- return true;
- }
- }
- Log.i(TAG, "no back camera");
- return false;
+ int backCameraId = CameraHolder.instance().getBackCameraId();
+ Log.i(TAG, backCameraId == -1 ? "no back camera" : ("back camera found: " + backCameraId));
+ return backCameraId != -1;
}
private void disableComponent(Context context, String klass) {
diff --git a/src/com/android/camera/FocusOverlayManager.java b/src/com/android/camera/FocusOverlayManager.java
index 253c08fb9..287890cbd 100644
--- a/src/com/android/camera/FocusOverlayManager.java
+++ b/src/com/android/camera/FocusOverlayManager.java
@@ -16,18 +16,22 @@
package com.android.camera;
-import android.annotation.TargetApi;
-import android.graphics.Matrix;
+import android.content.Context;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.Camera.Area;
import android.hardware.Camera.Parameters;
-import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
+import org.codeaurora.snapcam.R;
+import com.android.camera.app.CameraApp;
+import com.android.camera.ui.focus.CameraCoordinateTransformer;
+import com.android.camera.ui.focus.FocusRing;
+import com.android.camera.ui.motion.LinearScale;
import com.android.camera.util.CameraUtil;
import com.android.camera.util.UsageStatistics;
@@ -60,7 +64,9 @@ public class FocusOverlayManager {
private static final String TAG = "CAM_FocusManager";
private static final int RESET_TOUCH_FOCUS = 0;
- private static final int RESET_TOUCH_FOCUS_DELAY = 3000;
+
+ public static final float AF_REGION_BOX = 0.2f;
+ public static final float AE_REGION_BOX = 0.3f;
private int mState = STATE_IDLE;
public static final int STATE_IDLE = 0; // Focus is not active.
@@ -75,7 +81,7 @@ public class FocusOverlayManager {
private boolean mMeteringAreaSupported;
private boolean mLockAeAwbNeeded;
private boolean mAeAwbLock;
- private Matrix mMatrix;
+ private CameraCoordinateTransformer mCoordinateTransformer;
private boolean mMirror; // true if the camera is front-facing.
private int mDisplayOrientation;
@@ -93,19 +99,13 @@ public class FocusOverlayManager {
private boolean mTouchAFRunning = false;
private boolean mIsAFRunning = false;
- private FocusUI mUI;
+ private FocusRing mFocusRing;
private final Rect mPreviewRect = new Rect(0, 0, 0, 0);
- public interface FocusUI {
- public boolean hasFaces();
- public void clearFocus();
- public void setFocusPosition(int x, int y);
- public void onFocusStarted();
- public void onFocusSucceeded(boolean timeOut);
- public void onFocusFailed(boolean timeOut);
- public void pauseFaceDetection();
- public void resumeFaceDetection();
- }
+ private int mFocusTime; // time after touch-to-focus
+ private Point mDispSize;
+ private int mBottomMargin;
+ private int mTopMargin;
public interface Listener {
public void autoFocus();
@@ -114,6 +114,7 @@ public class FocusOverlayManager {
public void startFaceDetection();
public void stopFaceDetection();
public void setFocusParameters();
+ public void setFocusRatio(float ratio);
}
private class MainHandler extends Handler {
@@ -135,19 +136,25 @@ public class FocusOverlayManager {
public FocusOverlayManager(ComboPreferences preferences, String[] defaultFocusModes,
Parameters parameters, Listener listener,
- boolean mirror, Looper looper, FocusUI ui) {
+ boolean mirror, Looper looper, FocusRing focusRing, CameraActivity activity) {
mHandler = new MainHandler(looper);
- mMatrix = new Matrix();
mPreferences = preferences;
mDefaultFocusModes = defaultFocusModes;
setParameters(parameters);
mListener = listener;
setMirror(mirror);
- mUI = ui;
+ mDispSize = new Point();
+ activity.getWindowManager().getDefaultDisplay().getRealSize(mDispSize);
+ Context context = CameraApp.getContext();
+ mBottomMargin =
+ context.getResources().getDimensionPixelSize(R.dimen.preview_bottom_margin);
+ mTopMargin =
+ context.getResources().getDimensionPixelSize(R.dimen.preview_top_margin);
+ mFocusRing = focusRing;
}
- public void setPhotoUI(FocusUI ui) {
- mUI = ui;
+ public void setFocusRing(FocusRing focusRing) {
+ mFocusRing = focusRing;
}
public void setParameters(Parameters parameters) {
@@ -173,35 +180,29 @@ public class FocusOverlayManager {
public void setPreviewRect(Rect previewRect) {
if (!mPreviewRect.equals(previewRect)) {
mPreviewRect.set(previewRect);
- setMatrix();
+ mFocusRing.configurePreviewDimensions(CameraUtil.rectToRectF(mPreviewRect));
+ resetCoordinateTransformer();
+ mInitialized = true;
}
}
- /** Returns a copy of mPreviewRect so that outside class cannot modify preview
- * rect except deliberately doing so through the setter. */
- public Rect getPreviewRect() {
- return new Rect(mPreviewRect);
- }
-
public void setMirror(boolean mirror) {
mMirror = mirror;
- setMatrix();
+ resetCoordinateTransformer();
}
public void setDisplayOrientation(int displayOrientation) {
mDisplayOrientation = displayOrientation;
- setMatrix();
+ resetCoordinateTransformer();
}
- private void setMatrix() {
- if (mPreviewRect.width() != 0 && mPreviewRect.height() != 0) {
- Matrix matrix = new Matrix();
- CameraUtil.prepareMatrix(matrix, mMirror, mDisplayOrientation, getPreviewRect());
- // In face detection, the matrix converts the driver coordinates to UI
- // coordinates. In tap focus, the inverted matrix converts the UI
- // coordinates to driver coordinates.
- matrix.invert(mMatrix);
- mInitialized = true;
+ private void resetCoordinateTransformer() {
+ if (mPreviewRect.width() > 0 && mPreviewRect.height() > 0) {
+ mCoordinateTransformer = new CameraCoordinateTransformer(mMirror, mDisplayOrientation,
+ CameraUtil.rectToRectF(mPreviewRect));
+ } else {
+ Log.w(TAG, "The coordinate transformer could not be built because the preview rect"
+ + "did not have a width and height");
}
}
@@ -272,17 +273,27 @@ public class FocusOverlayManager {
}
}
+ // set touch-to-focus duration
+ public void setFocusTime(int time) {
+ mFocusTime = time;
+ }
+
public void onAutoFocus(boolean focused, boolean shutterButtonPressed) {
+ updateFocusDistance();
if (mState == STATE_FOCUSING_SNAP_ON_FINISH) {
// Take the picture no matter focus succeeds or fails. No need
// to play the AF sound if we're about to play the shutter
// sound.
if (focused) {
mState = STATE_SUCCESS;
+ // Lock exposure and white balance
+ if (mFocusTime != 200) {
+ setAeAwbLock(true);
+ mListener.setFocusParameters();
+ }
} else {
mState = STATE_FAIL;
}
- updateFocusUI();
capture();
} else if (mState == STATE_FOCUSING) {
// This happens when (1) user is half-pressing the focus key or
@@ -290,14 +301,18 @@ public class FocusOverlayManager {
// take the picture now.
if (focused) {
mState = STATE_SUCCESS;
+ // Lock exposure and white balance
+ if (mFocusTime != 200) {
+ setAeAwbLock(true);
+ mListener.setFocusParameters();
+ }
} else {
mState = STATE_FAIL;
}
- updateFocusUI();
// If this is triggered by touch focus, cancel focus after a
// while.
if (mFocusArea != null) {
- mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
+ mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, mFocusTime);
}
if (shutterButtonPressed) {
// Lock AE & AWB so users can half-press shutter and recompose.
@@ -313,32 +328,33 @@ public class FocusOverlayManager {
if (!mInitialized) return;
- // Ignore if the camera has detected some faces.
- if (mUI.hasFaces()) {
- mUI.clearFocus();
- if (mIsAFRunning) {
- mUI.onFocusSucceeded(true);
- mIsAFRunning = false;
- }
- return;
- }
-
// Ignore if we have requested autofocus. This method only handles
// continuous autofocus.
if (mState != STATE_IDLE) return;
// animate on false->true trasition only b/8219520
if (moving && !mPreviousMoving) {
- mUI.onFocusStarted();
+ mFocusRing.startPassiveFocus();
mIsAFRunning = true;
} else if (!moving) {
- mUI.onFocusSucceeded(true);
+ mFocusRing.stopFocusAnimations();
mIsAFRunning = false;
}
+
+ updateFocusDistance();
mPreviousMoving = moving;
}
- @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+ /** Returns width of auto focus region in pixels. */
+ private int getAFRegionSizePx() {
+ return (int) (Math.min(mPreviewRect.width(), mPreviewRect.height()) * AF_REGION_BOX);
+ }
+
+ /** Returns width of metering region in pixels. */
+ private int getAERegionSizePx() {
+ return (int) (Math.min(mPreviewRect.width(), mPreviewRect.height()) * AE_REGION_BOX);
+ }
+
private void initializeFocusAreas(int x, int y) {
if (mFocusArea == null) {
mFocusArea = new ArrayList<Object>();
@@ -346,10 +362,9 @@ public class FocusOverlayManager {
}
// Convert the coordinates to driver format.
- calculateTapArea(x, y, 1f, ((Area) mFocusArea.get(0)).rect);
+ ((Area) mFocusArea.get(0)).rect = computeCameraRectFromPreviewCoordinates(x, y, getAFRegionSizePx());
}
- @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void initializeMeteringAreas(int x, int y) {
if (mMeteringArea == null) {
mMeteringArea = new ArrayList<Object>();
@@ -359,7 +374,7 @@ public class FocusOverlayManager {
// Convert the coordinates to driver format.
// AE area is bigger because exposure is sensitive and
// easy to over- or underexposure if area is too small.
- calculateTapArea(x, y, 1.5f, ((Area) mMeteringArea.get(0)).rect);
+ ((Area) mMeteringArea.get(0)).rect = computeCameraRectFromPreviewCoordinates(x, y, getAERegionSizePx());
}
private void resetMeteringAreas() {
@@ -377,7 +392,10 @@ public class FocusOverlayManager {
mState == STATE_SUCCESS || mState == STATE_FAIL)) {
cancelAutoFocus();
}
- if (mPreviewRect.width() == 0 || mPreviewRect.height() == 0) return;
+ if (mPreviewRect.width() == 0 || mPreviewRect.height() == 0 ||
+ (y > (mDispSize.y - mBottomMargin) || y < mTopMargin)) {
+ return;
+ }
// Initialize variables.
// Initialize mFocusArea.
if (mFocusAreaSupported) {
@@ -388,8 +406,8 @@ public class FocusOverlayManager {
initializeMeteringAreas(x, y);
}
- // Use margin to set the focus indicator to the touched area.
- mUI.setFocusPosition(x, y);
+ mFocusRing.startActiveFocus();
+ mFocusRing.setFocusLocation(x, y);
if (mZslEnabled) {
mTouchAFRunning = true;
@@ -398,15 +416,18 @@ public class FocusOverlayManager {
// Stop face detection because we want to specify focus and metering area.
mListener.stopFaceDetection();
+ if (mFocusTime == 200) {
+ setAeAwbLock(true);
+ mListener.setFocusParameters();
+ }
+
// Set the focus area and metering area.
mListener.setFocusParameters();
if (mFocusAreaSupported) {
autoFocus();
} else { // Just show the indicator in all other cases.
- updateFocusUI();
- // Reset the metering area in 3 seconds.
mHandler.removeMessages(RESET_TOUCH_FOCUS);
- mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
+ mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, mFocusTime);
}
}
@@ -418,7 +439,6 @@ public class FocusOverlayManager {
// If auto focus was in progress, it would have been stopped.
mState = STATE_IDLE;
resetTouchFocus();
- updateFocusUI();
}
public void onCameraReleased() {
@@ -430,7 +450,8 @@ public class FocusOverlayManager {
Log.v(TAG, "Start autofocus.");
mListener.autoFocus();
mState = STATE_FOCUSING;
- updateFocusUI();
+ // Pause the face view because the driver will keep sending face
+ // callbacks after the focus completes.
mHandler.removeMessages(RESET_TOUCH_FOCUS);
}
@@ -441,10 +462,9 @@ public class FocusOverlayManager {
// Otherwise, focus mode stays at auto and the tap area passed to the
// driver is not reset.
resetTouchFocus();
+ setAeAwbLock(false);
mListener.cancelAutoFocus();
- mUI.resumeFaceDetection();
mState = STATE_IDLE;
- updateFocusUI();
mHandler.removeMessages(RESET_TOUCH_FOCUS);
}
@@ -455,7 +475,7 @@ public class FocusOverlayManager {
}
}
- public String getFocusMode() {
+ public String getFocusMode(boolean fromVideo) {
if (mOverrideFocusMode != null) return mOverrideFocusMode;
if (mParameters == null) return Parameters.FOCUS_MODE_AUTO;
List<String> supportedFocusModes = mParameters.getSupportedFocusModes();
@@ -465,8 +485,13 @@ public class FocusOverlayManager {
mFocusMode = Parameters.FOCUS_MODE_AUTO;
} else {
// The default is continuous autofocus.
- mFocusMode = mPreferences.getString(
- CameraSettings.KEY_FOCUS_MODE, null);
+ if (fromVideo) {
+ mFocusMode = mPreferences.getString(
+ CameraSettings.KEY_VIDEOCAMERA_FOCUS_MODE, null);
+ } else {
+ mFocusMode = mPreferences.getString(
+ CameraSettings.KEY_FOCUS_MODE, null);
+ }
// Try to find a supported focus mode from the default list.
if (mFocusMode == null) {
@@ -500,41 +525,18 @@ public class FocusOverlayManager {
return mMeteringArea;
}
- public void updateFocusUI() {
- if (!mInitialized) return;
- // Show only focus indicator or face indicator.
-
- if (mState == STATE_IDLE) {
- if (mFocusArea == null) {
- mUI.clearFocus();
- } else {
- // Users touch on the preview and the indicator represents the
- // metering area. Either focus area is not supported or
- // autoFocus call is not required.
- mUI.onFocusStarted();
- }
- } else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
- mUI.onFocusStarted();
+ public void restartTouchFocusTimer() {
+ if (mZslEnabled && (mFocusArea != null) && (mFocusTime != 0x7FFFFFFF)) {
+ mHandler.removeMessages(RESET_TOUCH_FOCUS);
+ mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, mFocusTime);
} else {
- if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)) {
- // TODO: check HAL behavior and decide if this can be removed.
- mUI.onFocusSucceeded(false);
- } else if (mState == STATE_SUCCESS) {
- mUI.onFocusSucceeded(false);
- } else if (mState == STATE_FAIL) {
- mUI.onFocusFailed(false);
- }
+ resetTouchFocus();
}
}
public void resetTouchFocus() {
if (!mInitialized) return;
- // Put focus indicator to the center. clear reset position
- if (mUI != null) {
- mUI.clearFocus();
- }
- // Initialize mFocusArea.
mFocusArea = null;
// Initialize mMeteringArea.
mMeteringArea = null;
@@ -549,16 +551,14 @@ public class FocusOverlayManager {
}
}
- private void calculateTapArea(int x, int y, float areaMultiple, Rect rect) {
- int areaSize = (int) (getAreaSize() * areaMultiple);
- int left = CameraUtil.clamp(x - areaSize / 2, mPreviewRect.left,
- mPreviewRect.right - areaSize);
- int top = CameraUtil.clamp(y - areaSize / 2, mPreviewRect.top,
- mPreviewRect.bottom - areaSize);
+ private Rect computeCameraRectFromPreviewCoordinates(int x, int y, int size) {
+ int left = CameraUtil.clamp(x - size / 2, mPreviewRect.left,
+ mPreviewRect.right - size);
+ int top = CameraUtil.clamp(y - size / 2, mPreviewRect.top,
+ mPreviewRect.bottom - size);
- RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
- mMatrix.mapRect(rectF);
- CameraUtil.rectFToRect(rectF, rect);
+ RectF rectF = new RectF(left, top, left + size, top + size);
+ return CameraUtil.rectFToRect(mCoordinateTransformer.toCameraSpace(rectF));
}
private int getAreaSize() {
@@ -600,10 +600,8 @@ public class FocusOverlayManager {
}
private boolean needAutoFocusCall() {
- String focusMode = getFocusMode();
- return !(focusMode.equals(Parameters.FOCUS_MODE_INFINITY)
- || focusMode.equals(Parameters.FOCUS_MODE_FIXED)
- || focusMode.equals(Parameters.FOCUS_MODE_EDOF));
+ return getFocusMode(false).equals(Parameters.FOCUS_MODE_AUTO) &&
+ !(mZslEnabled && (mHandler.hasMessages(RESET_TOUCH_FOCUS)));
}
public void setZslEnable(boolean value) {
@@ -618,4 +616,92 @@ public class FocusOverlayManager {
return mTouchAFRunning;
}
+ private static class FocusInfo {
+ public final float near;
+ public final float far;
+ public final float current;
+
+ public FocusInfo(float _near, float _far, float _current) {
+ near = _near;
+ far = _far;
+ current = _current;
+ }
+ }
+
+ private FocusInfo getFocusInfoFromParameters(
+ String currentParam, String minParam, String maxParam) {
+ try {
+ String current = mParameters.get(currentParam);
+ if (current != null) {
+ float min = Float.parseFloat(mParameters.get(minParam));
+ float max = Float.parseFloat(mParameters.get(maxParam));
+ if (!(min == 0.0f && max == 0.0f)) {
+ return new FocusInfo(min, max, Float.parseFloat(current));
+ }
+ }
+ } catch (Exception e) {
+ // skip it
+ }
+ return null;
+ }
+
+ private FocusInfo getFocusInfo() {
+ // focus positon is horrifically buggy on some HALs. try to
+ // make the best of it and attempt a few different techniques
+ // to get an accurate measurement
+
+ // older QCOM (Bacon)
+ FocusInfo info = getFocusInfoFromParameters("current-focus-position",
+ "min-focus-pos-index", "max-focus-pos-index");
+ if (info != null) {
+ return info;
+ }
+
+ // newer QCOM (Crackling)
+ info = getFocusInfoFromParameters("cur-focus-scale",
+ "min-focus-pos-ratio", "max-focus-pos-ratio");
+ if (info != null) {
+ return info;
+ }
+
+ return null;
+ }
+
+ /**
+ * Compute the focus range from the camera characteristics and build
+ * a linear scale model that maps a focus distance to a ratio between
+ * the min and max range.
+ */
+ private LinearScale getDiopterToRatioCalculator(FocusInfo focusInfo) {
+ // From the android documentation:
+ //
+ // 0.0f represents farthest focus, and LENS_INFO_MINIMUM_FOCUS_DISTANCE
+ // represents the nearest focus the device can achieve.
+ //
+ // Example:
+ //
+ // Infinity Hyperfocal Minimum Camera
+ // <----------|-----------------------------| |
+ // [0.0] [0.31] [14.29]
+ if (focusInfo.near == 0.0f && focusInfo.far == 0.0f) {
+ return new LinearScale(0, 0, 0, 0);
+ }
+
+ if (focusInfo.near > focusInfo.far) {
+ return new LinearScale(focusInfo.far, focusInfo.near, 0, 1);
+ }
+
+ return new LinearScale(focusInfo.near, focusInfo.far, 0, 1);
+ }
+
+ private void updateFocusDistance() {
+ final FocusInfo focusInfo = getFocusInfo();
+ if (focusInfo != null) {
+ LinearScale range = getDiopterToRatioCalculator(focusInfo);
+ if (range.isInDomain(focusInfo.current) && (mFocusRing.isPassiveFocusRunning() ||
+ mFocusRing.isActiveFocusRunning())) {
+ mListener.setFocusRatio(range.scale(focusInfo.current));
+ }
+ }
+ }
}
diff --git a/src/com/android/camera/FocusStateListener.java b/src/com/android/camera/FocusStateListener.java
index 6c536c53b..459e4ec23 100644
--- a/src/com/android/camera/FocusStateListener.java
+++ b/src/com/android/camera/FocusStateListener.java
@@ -44,31 +44,31 @@ public class FocusStateListener {
switch (focusState) {
case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN:
Log.d(TAG, "CONTROL_AF_STATE_ACTIVE_SCAN onFocusStarted");
- mUI.onFocusStarted();
+ mUI.getFocusRing().startActiveFocus();
break;
case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
Log.d(TAG, "CONTROL_AF_STATE_FOCUSED_LOCKED onFocusSucceeded");
- mUI.onFocusSucceeded(false);
+ mUI.getFocusRing().stopFocusAnimations();
break;
case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
Log.d(TAG, "CONTROL_AF_STATE_NOT_FOCUSED_LOCKED onFocusFailed");
- mUI.onFocusFailed(false);
+ mUI.getFocusRing().stopFocusAnimations();
break;
case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
Log.d(TAG, "CONTROL_AF_STATE_PASSIVE_FOCUSED onFocusSucceeded");
- mUI.onFocusSucceeded(true);
+ mUI.getFocusRing().stopFocusAnimations();
break;
case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
Log.d(TAG, "CONTROL_AF_STATE_PASSIVE_SCAN onFocusStarted");
- mUI.onFocusStarted();
+ mUI.getFocusRing().startPassiveFocus();
break;
case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
Log.d(TAG, "CONTROL_AF_STATE_PASSIVE_UNFOCUSED onFocusFailed");
- mUI.onFocusFailed(true);
+ mUI.getFocusRing().stopFocusAnimations();
break;
case CaptureResult.CONTROL_AF_STATE_INACTIVE:
Log.d(TAG, "CONTROL_AF_STATE_INACTIVE clearFocus");
- mUI.clearFocus();
+ mUI.getFocusRing().stopFocusAnimations();
break;
}
}
diff --git a/src/com/android/camera/ListPreference.java b/src/com/android/camera/ListPreference.java
index ae37356e1..50afc0849 100644
--- a/src/com/android/camera/ListPreference.java
+++ b/src/com/android/camera/ListPreference.java
@@ -184,7 +184,11 @@ public class ListPreference extends CameraPreference {
}
public String getLabel() {
- return mLabels[findIndexOfValue(getValue())].toString();
+ int index = findIndexOfValue(getValue());
+ if (index < 0) {
+ return findSupportedDefaultValue();
+ }
+ return mLabels[index].toString();
}
protected void persistStringValue(String value) {
@@ -203,6 +207,7 @@ public class ListPreference extends CameraPreference {
ArrayList<CharSequence> entries = new ArrayList<CharSequence>();
ArrayList<CharSequence> entryValues = new ArrayList<CharSequence>();
for (int i = 0, len = mEntryValues.length; i < len; i++) {
+ if (i >= mEntries.length) break;
if (supported.indexOf(mEntryValues[i].toString()) >= 0) {
entries.add(mEntries[i]);
entryValues.add(mEntryValues[i]);
diff --git a/src/com/android/camera/LocationManager.java b/src/com/android/camera/LocationManager.java
index 5aedf060e..2ae901aed 100755
--- a/src/com/android/camera/LocationManager.java
+++ b/src/com/android/camera/LocationManager.java
@@ -79,7 +79,7 @@ public class LocationManager {
}
private boolean hasLoationPermission() {
- return mContext.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
+ return mContext.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED;
}
diff --git a/src/com/android/camera/MenuController.java b/src/com/android/camera/MenuController.java
index 97240cb18..63815f9b7 100644
--- a/src/com/android/camera/MenuController.java
+++ b/src/com/android/camera/MenuController.java
@@ -104,6 +104,7 @@ public class MenuController {
return;
}
}
+ index = index % ((IconListPreference) pref).getLargeIconIds().length;
((ImageView) switcher).setImageResource(pref.getLargeIconIds()[index]);
}
diff --git a/src/com/android/camera/Mosaic.java b/src/com/android/camera/Mosaic.java
index a9bc32e12..829efa5b2 100644
--- a/src/com/android/camera/Mosaic.java
+++ b/src/com/android/camera/Mosaic.java
@@ -93,7 +93,7 @@ public class Mosaic {
static {
- System.loadLibrary("jni_snapcammosaic");
+ System.loadLibrary("jni_snapmosaic");
}
/**
diff --git a/src/com/android/camera/MosaicFrameProcessor.java b/src/com/android/camera/MosaicFrameProcessor.java
index cb305344d..2e027b3e3 100644
--- a/src/com/android/camera/MosaicFrameProcessor.java
+++ b/src/com/android/camera/MosaicFrameProcessor.java
@@ -24,7 +24,7 @@ import android.util.Log;
public class MosaicFrameProcessor {
private static final String TAG = "MosaicFrameProcessor";
private static final int NUM_FRAMES_IN_BUFFER = 2;
- private static final int MAX_NUMBER_OF_FRAMES = 100;
+ private static final int MAX_NUMBER_OF_FRAMES = 100 * 2; // We need 200 frames for 360 degrees
private static final int MOSAIC_RET_CODE_INDEX = 10;
private static final int FRAME_COUNT_INDEX = 9;
private static final int X_COORD_INDEX = 2;
diff --git a/src/com/android/camera/MosaicRenderer.java b/src/com/android/camera/MosaicRenderer.java
index 5006b364d..bcbaf7227 100644
--- a/src/com/android/camera/MosaicRenderer.java
+++ b/src/com/android/camera/MosaicRenderer.java
@@ -24,7 +24,7 @@ public class MosaicRenderer
{
static
{
- System.loadLibrary("jni_snapcammosaic");
+ System.loadLibrary("jni_snapmosaic");
}
/**
diff --git a/src/com/android/camera/OnScreenIndicators.java b/src/com/android/camera/OnScreenIndicators.java
deleted file mode 100644
index 67cbad1c9..000000000
--- a/src/com/android/camera/OnScreenIndicators.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * 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;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.hardware.Camera;
-import android.hardware.Camera.Parameters;
-import android.util.Log;
-import android.view.View;
-import android.widget.ImageView;
-
-import org.codeaurora.snapcam.R;
-
-/**
- * The on-screen indicators of the pie menu button. They show the camera
- * settings in the viewfinder.
- */
-public class OnScreenIndicators {
- public static final String SCENE_MODE_HDR_PLUS = "hdr_plus";
-
- private final int[] mWBArray;
- private final View mOnScreenIndicators;
- private final ImageView mExposureIndicator;
- private final ImageView mFlashIndicator;
- private final ImageView mSceneIndicator;
- private final ImageView mLocationIndicator;
- private final ImageView mTimerIndicator;
- private final ImageView mWBIndicator;
-
- public OnScreenIndicators(Context ctx, View onScreenIndicatorsView) {
- TypedArray iconIds = ctx.getResources().obtainTypedArray(
- R.array.camera_wb_indicators);
- final int n = iconIds.length();
- mWBArray = new int[n];
- for (int i = 0; i < n; i++) {
- mWBArray[i] = iconIds.getResourceId(i, R.drawable.ic_indicator_wb_off);
- }
- mOnScreenIndicators = onScreenIndicatorsView;
- mExposureIndicator = (ImageView) onScreenIndicatorsView.findViewById(
- R.id.menu_exposure_indicator);
- mFlashIndicator = (ImageView) onScreenIndicatorsView.findViewById(
- R.id.menu_flash_indicator);
- mSceneIndicator = (ImageView) onScreenIndicatorsView.findViewById(
- R.id.menu_scenemode_indicator);
- mLocationIndicator = (ImageView) onScreenIndicatorsView.findViewById(
- R.id.menu_location_indicator);
- mTimerIndicator = (ImageView) onScreenIndicatorsView.findViewById(
- R.id.menu_timer_indicator);
- mWBIndicator = (ImageView) onScreenIndicatorsView.findViewById(
- R.id.menu_wb_indicator);
- mExposureIndicator.setVisibility(View.GONE);
- mFlashIndicator.setVisibility(View.GONE);
- mSceneIndicator.setVisibility(View.GONE);
- mLocationIndicator.setVisibility(View.GONE);
- mTimerIndicator.setVisibility(View.GONE);
- mWBIndicator.setVisibility(View.GONE);
- }
-
- /**
- * Resets all indicators to show the default values.
- */
- public void resetToDefault() {
- updateExposureOnScreenIndicator(0);
- updateFlashOnScreenIndicator(Parameters.FLASH_MODE_OFF);
- updateSceneOnScreenIndicator(Parameters.SCENE_MODE_AUTO);
- updateWBIndicator(2);
- updateTimerIndicator(false);
- updateLocationIndicator(false);
- }
-
- /**
- * Sets the exposure indicator using exposure compensations step rounding.
- */
- public void updateExposureOnScreenIndicator(Camera.Parameters params, int value) {
- if (mExposureIndicator == null) {
- return;
- }
- float step = params.getExposureCompensationStep();
- value = Math.round(value * step);
- updateExposureOnScreenIndicator(value);
- }
-
- /**
- * Set the exposure indicator to the given value.
- *
- * @param value Value between -3 and 3. If outside this range, 0 is used by
- * default.
- */
- public void updateExposureOnScreenIndicator(int value) {
- int id = 0;
- switch(value) {
- case -3:
- id = R.drawable.ic_indicator_ev_n3;
- break;
- case -2:
- id = R.drawable.ic_indicator_ev_n2;
- break;
- case -1:
- id = R.drawable.ic_indicator_ev_n1;
- break;
- case 0:
- id = R.drawable.ic_indicator_ev_0;
- break;
- case 1:
- id = R.drawable.ic_indicator_ev_p1;
- break;
- case 2:
- id = R.drawable.ic_indicator_ev_p2;
- break;
- case 3:
- id = R.drawable.ic_indicator_ev_p3;
- break;
- }
- mExposureIndicator.setImageResource(R.drawable.ic_settings);
- }
-
- public void updateWBIndicator(int wbIndex) {
- if (mWBIndicator == null) return;
- mWBIndicator.setImageResource(mWBArray[wbIndex]);
- }
-
- public void updateTimerIndicator(boolean on) {
- if (mTimerIndicator == null) return;
- mTimerIndicator.setImageResource(on ? R.drawable.ic_indicator_timer_on
- : R.drawable.ic_indicator_timer_off);
- }
-
- public void updateLocationIndicator(boolean on) {
- if (mLocationIndicator == null) return;
- mLocationIndicator.setImageResource(on ? R.drawable.ic_indicator_loc_on
- : R.drawable.ic_indicator_loc_off);
- }
-
- /**
- * Set the flash indicator to the given value.
- *
- * @param value One of Parameters.FLASH_MODE_OFF,
- * Parameters.FLASH_MODE_AUTO, Parameters.FLASH_MODE_ON.
- */
- public void updateFlashOnScreenIndicator(String value) {
- if (mFlashIndicator == null) {
- return;
- }
- if (value == null || Parameters.FLASH_MODE_OFF.equals(value)) {
- mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_off);
- } else {
- if (Parameters.FLASH_MODE_AUTO.equals(value)) {
- mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_auto);
- } else if (Parameters.FLASH_MODE_ON.equals(value)
- || Parameters.FLASH_MODE_TORCH.equals(value)) {
- mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_on);
- } else {
- mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_off);
- }
- }
- }
-
- /**
- * Set the scene indicator depending on the given scene mode.
- *
- * @param value the current Parameters.SCENE_MODE_* value or
- * {@link #SCENE_MODE_HDR_PLUS}.
- */
- public void updateSceneOnScreenIndicator(String value) {
- if (mSceneIndicator == null) {
- return;
- }
-
- if (SCENE_MODE_HDR_PLUS.equals(value)) {
- mSceneIndicator.setImageResource(R.drawable.ic_indicator_hdr_plus_on);
- } else if ((value == null) || Parameters.SCENE_MODE_AUTO.equals(value)) {
- mSceneIndicator.setImageResource(R.drawable.ic_indicator_sce_off);
- } else if (Parameters.SCENE_MODE_HDR.equals(value)) {
- mSceneIndicator.setImageResource(R.drawable.ic_indicator_sce_hdr);
- } else {
- mSceneIndicator.setImageResource(R.drawable.ic_indicator_sce_on);
- }
- }
-
- /**
- * Sets the visibility of all indicators.
- *
- * @param visibility View.VISIBLE, View.GONE etc.
- */
- public void setVisibility(int visibility) {
- mOnScreenIndicators.setVisibility(visibility);
- }
-}
diff --git a/src/com/android/camera/PanoCaptureUI.java b/src/com/android/camera/PanoCaptureUI.java
index a25ff9f94..2894e683c 100644
--- a/src/com/android/camera/PanoCaptureUI.java
+++ b/src/com/android/camera/PanoCaptureUI.java
@@ -80,9 +80,6 @@ public class PanoCaptureUI implements
private ImageView mSceneModeLabelCloseIcon;
private AlertDialog mSceneModeInstructionalDialog = null;
- // Small indicators which show the camera settings in the viewfinder.
- private OnScreenIndicators mOnScreenIndicators;
-
private AutoFitSurfaceView mSurfaceView = null;
private Matrix mMatrix = null;
private boolean mUIhidden = false;
@@ -225,7 +222,6 @@ public class PanoCaptureUI implements
mSceneModeLabelRect.setVisibility(View.GONE);
}
});
- initIndicators();
Point size = new Point();
mActivity.getWindowManager().getDefaultDisplay().getSize(size);
@@ -278,11 +274,6 @@ public class PanoCaptureUI implements
return mRootView;
}
- private void initIndicators() {
- mOnScreenIndicators = new OnScreenIndicators(mActivity,
- mRootView.findViewById(R.id.on_screen_indicators));
- }
-
public void onCameraOpened() {
}
@@ -354,13 +345,6 @@ public class PanoCaptureUI implements
} else {
hideUI();
}
- setShowMenu(previewFocused);
- }
-
- private void setShowMenu(boolean show) {
- if (mOnScreenIndicators != null) {
- mOnScreenIndicators.setVisibility(show ? View.VISIBLE : View.GONE);
- }
}
public boolean collapseCameraControls() {
diff --git a/src/com/android/camera/PanoProgressBar.java b/src/com/android/camera/PanoProgressBar.java
index d20878a84..45f08a53e 100644
--- a/src/com/android/camera/PanoProgressBar.java
+++ b/src/com/android/camera/PanoProgressBar.java
@@ -142,7 +142,9 @@ class PanoProgressBar extends ImageView {
// When user move to the opposite direction more than 10 degrees,
// change the direction and stop the capture progress in PanoramaModule.
if (Math.abs(mOldProgress) - Math.abs(progress) > 10) {
- mListener.onDirectionChange(mDirection/2 + 1);
+ if (mListener != null) {
+ mListener.onDirectionChange(mDirection / 2 + 1);
+ }
return;
}
// mDirection might be modified by setRightIncreasing() above. Need to check again.
diff --git a/src/com/android/camera/PermissionsActivity.java b/src/com/android/camera/PermissionsActivity.java
index 91699c34f..fb0c080db 100755
--- a/src/com/android/camera/PermissionsActivity.java
+++ b/src/com/android/camera/PermissionsActivity.java
@@ -79,7 +79,7 @@ public class PermissionsActivity extends Activity {
mFlagHasStoragePermission = true;
}
- if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
+ if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
mNumPermissionsToRequest++;
mShouldRequestLocationPermission = true;
@@ -119,7 +119,7 @@ public class PermissionsActivity extends Activity {
}
if (mShouldRequestLocationPermission) {
permissionsToRequest[permissionsRequestIndex] =
- Manifest.permission.ACCESS_COARSE_LOCATION;
+ Manifest.permission.ACCESS_FINE_LOCATION;
mIndexPermissionRequestLocation = permissionsRequestIndex;
}
requestPermissions(permissionsToRequest, PERMISSION_REQUEST_CODE);
diff --git a/src/com/android/camera/PhotoMenu.java b/src/com/android/camera/PhotoMenu.java
index 7debfc7ef..4f6c88688 100644
--- a/src/com/android/camera/PhotoMenu.java
+++ b/src/com/android/camera/PhotoMenu.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013-2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -94,7 +95,7 @@ public class PhotoMenu extends MenuController
private static final int MODE_SCENE = 0;
private static final int MODE_FILTER = 1;
private static final int MODE_MAKEUP = 2;
- private static final int DEVELOPER_MENU_TOUCH_COUNT = 10;
+ private static final int DEVELOPER_MENU_TOUCH_COUNT = 7;
private int mSceneStatus;
private View mHdrSwitcher;
private View mTsMakeupSwitcher;
@@ -112,7 +113,7 @@ public class PhotoMenu extends MenuController
private String mPrevSavedCDS;
private boolean mIsTNREnabled = false;
private boolean mIsCDSUpdated = false;
- private int privateCounter = 0;
+ private int mPrivateCounter = 0;
private static final int ANIMATION_DURATION = 300;
private static final int CLICK_THRESHOLD = 200;
private int previewMenuSize;
@@ -193,9 +194,20 @@ public class PhotoMenu extends MenuController
CameraSettings.KEY_EXPOSURE,
CameraSettings.KEY_WHITE_BALANCE,
CameraSettings.KEY_QC_CHROMA_FLASH,
+ CameraSettings.KEY_FOCUS_TIME,
+ CameraSettings.KEY_SHUTTER_SPEED,
CameraSettings.KEY_REDEYE_REDUCTION,
CameraSettings.KEY_SELFIE_MIRROR,
- CameraSettings.KEY_SHUTTER_SOUND
+ CameraSettings.KEY_SHUTTER_SOUND,
+ CameraSettings.KEY_POWER_SHUTTER,
+ CameraSettings.KEY_MAX_BRIGHTNESS,
+ CameraSettings.KEY_SATURATION,
+ CameraSettings.KEY_CONTRAST,
+ CameraSettings.KEY_SHARPNESS,
+ CameraSettings.KEY_AUTOEXPOSURE,
+ CameraSettings.KEY_ANTIBANDING,
+ CameraSettings.KEY_DENOISE,
+ CameraSettings.KEY_AUTO_HDR
};
mOtherKeys2 = new String[] {
@@ -213,25 +225,27 @@ public class PhotoMenu extends MenuController
CameraSettings.KEY_WHITE_BALANCE,
CameraSettings.KEY_QC_CHROMA_FLASH,
CameraSettings.KEY_FOCUS_MODE,
+ CameraSettings.KEY_FOCUS_TIME,
+ CameraSettings.KEY_SHUTTER_SPEED,
CameraSettings.KEY_REDEYE_REDUCTION,
+ CameraSettings.KEY_POWER_SHUTTER,
+ CameraSettings.KEY_MAX_BRIGHTNESS,
+ CameraSettings.KEY_SATURATION,
+ CameraSettings.KEY_CONTRAST,
+ CameraSettings.KEY_SHARPNESS,
+ CameraSettings.KEY_AUTOEXPOSURE,
+ CameraSettings.KEY_ANTIBANDING,
+ CameraSettings.KEY_DENOISE,
CameraSettings.KEY_AUTO_HDR,
CameraSettings.KEY_HDR_MODE,
- CameraSettings.KEY_HDR_NEED_1X,
CameraSettings.KEY_CDS_MODE,
CameraSettings.KEY_TNR_MODE,
CameraSettings.KEY_HISTOGRAM,
CameraSettings.KEY_ZSL,
CameraSettings.KEY_TIMER_SOUND_EFFECTS,
CameraSettings.KEY_FACE_RECOGNITION,
- CameraSettings.KEY_TOUCH_AF_AEC,
CameraSettings.KEY_SELECTABLE_ZONE_AF,
CameraSettings.KEY_PICTURE_FORMAT,
- CameraSettings.KEY_SATURATION,
- CameraSettings.KEY_CONTRAST,
- CameraSettings.KEY_SHARPNESS,
- CameraSettings.KEY_AUTOEXPOSURE,
- CameraSettings.KEY_ANTIBANDING,
- CameraSettings.KEY_DENOISE,
CameraSettings.KEY_ADVANCED_FEATURES,
CameraSettings.KEY_AE_BRACKET_HDR,
CameraSettings.KEY_INSTANT_CAPTURE,
@@ -438,7 +452,7 @@ public class PhotoMenu extends MenuController
public void animateFadeIn(final ListView v) {
ViewPropertyAnimator vp = v.animate();
- vp.alpha(0.85f).setDuration(ANIMATION_DURATION);
+ vp.alpha(1f).setDuration(ANIMATION_DURATION);
vp.start();
}
@@ -693,7 +707,6 @@ public class PhotoMenu extends MenuController
|| ((autohdr != null) && autohdr.equals("enable"))) {
popup1.setPreferenceEnabled(CameraSettings.KEY_FOCUS_MODE, false);
popup1.setPreferenceEnabled(CameraSettings.KEY_AUTOEXPOSURE, false);
- popup1.setPreferenceEnabled(CameraSettings.KEY_TOUCH_AF_AEC, false);
popup1.setPreferenceEnabled(CameraSettings.KEY_SATURATION, false);
popup1.setPreferenceEnabled(CameraSettings.KEY_CONTRAST, false);
popup1.setPreferenceEnabled(CameraSettings.KEY_SHARPNESS, false);
@@ -756,7 +769,6 @@ public class PhotoMenu extends MenuController
popup1.setPreferenceEnabled(CameraSettings.KEY_REDEYE_REDUCTION, false);
popup1.setPreferenceEnabled(CameraSettings.KEY_EXPOSURE, false);
popup1.setPreferenceEnabled(CameraSettings.KEY_COLOR_EFFECT, false);
- popup1.setPreferenceEnabled(CameraSettings.KEY_TOUCH_AF_AEC, false);
popup1.setPreferenceEnabled(CameraSettings.KEY_SCENE_MODE, false);
popup1.setPreferenceEnabled(CameraSettings.KEY_INSTANT_CAPTURE, false);
setPreference(CameraSettings.KEY_CAMERA_HDR, mSettingOff);
@@ -812,6 +824,7 @@ public class PhotoMenu extends MenuController
int index = pref.findIndexOfValue(pref.getValue());
if (!pref.getUseSingleIcon() && iconIds != null) {
// Each entry has a corresponding icon.
+ index = index % iconIds.length;
resid = iconIds[index];
} else {
// The preference only has a single icon to represent it.
@@ -838,8 +851,9 @@ public class PhotoMenu extends MenuController
CharSequence[] values = pref.getEntryValues();
index = (index + 1) % values.length;
pref.setValueIndex(index);
+ int iconListLength = ((IconListPreference) pref).getLargeIconIds().length;
((ImageView) v).setImageResource(
- ((IconListPreference) pref).getLargeIconIds()[index]);
+ ((IconListPreference) pref).getLargeIconIds()[index % iconListLength]);
if (prefKey.equals(CameraSettings.KEY_CAMERA_ID))
mListener.onCameraPickerClicked(index);
reloadPreference(pref);
@@ -1059,11 +1073,8 @@ public class PhotoMenu extends MenuController
onSettingChanged(pref);
updateSceneModeIcon(pref);
for (View v1 : views) {
- v1.setBackgroundResource(R.drawable.scene_mode_view_border);
+ v1.setActivated(v1 == v);
}
- View border = v.findViewById(R.id.border);
- border.setBackgroundResource(R.drawable.scene_mode_view_border_selected);
- animateSlideOutPreviewMenu();
}
}
@@ -1071,10 +1082,8 @@ public class PhotoMenu extends MenuController
}
});
- View border = layout2.findViewById(R.id.border);
- views[j] = border;
- if (i == init)
- border.setBackgroundResource(R.drawable.scene_mode_view_border_selected);
+ views[j] = layout2;
+ layout2.setActivated(i == init);
imageView.setImageResource(thumbnails[i]);
label.setText(entries[i]);
layout.addView(layout2);
@@ -1210,19 +1219,16 @@ public class PhotoMenu extends MenuController
changeFilterModeControlIcon(pref.getValue());
onSettingChanged(pref);
for (View v1 : views) {
- v1.setBackground(null);
+ v1.setActivated(v1 == v);
}
- ImageView image = (ImageView) v.findViewById(R.id.image);
- image.setBackgroundColor(0xff33b5e5);
}
}
return true;
}
});
- views[j] = imageView;
- if (i == init)
- imageView.setBackgroundColor(0xff33b5e5);
+ views[j] = layout2;
+ layout2.setActivated(i == init);
TextView label = (TextView) layout2.findViewById(R.id.label);
imageView.setImageResource(thumbnails[i]);
label.setText(entries[i]);
@@ -1291,21 +1297,6 @@ public class PhotoMenu extends MenuController
}
public void onPreferenceClicked(ListPreference pref, int y) {
- if (!mActivity.isDeveloperMenuEnabled()) {
- if (pref.getKey().equals(CameraSettings.KEY_REDEYE_REDUCTION)) {
- privateCounter++;
- if (privateCounter >= DEVELOPER_MENU_TOUCH_COUNT) {
- mActivity.enableDeveloperMenu();
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(mActivity);
- prefs.edit().putBoolean(CameraSettings.KEY_DEVELOPER_MENU, true).apply();
- RotateTextToast.makeText(mActivity,
- "Camera developer option is enabled now", Toast.LENGTH_SHORT).show();
- }
- } else {
- privateCounter = 0;
- }
- }
LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
ListSubMenu basic = (ListSubMenu) inflater.inflate(
@@ -1321,6 +1312,31 @@ public class PhotoMenu extends MenuController
mUI.showPopup(mListSubMenu, 2, true);
}
mPopupStatus = POPUP_SECOND_LEVEL;
+
+ // Developer menu
+ if (pref.getKey().equals(CameraSettings.KEY_MAX_BRIGHTNESS)) {
+ mPrivateCounter++;
+ if (mPrivateCounter >= DEVELOPER_MENU_TOUCH_COUNT) {
+ SharedPreferences prefs = PreferenceManager
+ .getDefaultSharedPreferences(mActivity);
+ if (!mActivity.isDeveloperMenuEnabled()) {
+ mActivity.enableDeveloperMenu();
+ prefs.edit().putBoolean(CameraSettings.KEY_DEVELOPER_MENU, true).apply();
+ closeAllView();
+ RotateTextToast.makeText(mActivity,
+ R.string.developer_menu_enabled, Toast.LENGTH_SHORT).show();
+ } else {
+ mActivity.disableDeveloperMenu();
+ prefs.edit().putBoolean(CameraSettings.KEY_DEVELOPER_MENU, false).apply();
+ closeAllView();
+ RotateTextToast.makeText(mActivity,
+ R.string.developer_menu_disabled, Toast.LENGTH_SHORT).show();
+ }
+ mPrivateCounter = 0;
+ }
+ } else {
+ mPrivateCounter = 0;
+ }
}
public void onListMenuTouched() {
@@ -1414,7 +1430,7 @@ public class PhotoMenu extends MenuController
} else if (notSame(pref,CameraSettings.KEY_FLASH_MODE,"Off")) {
ListPreference aePref =
mPreferenceGroup.findPreference(CameraSettings.KEY_AE_BRACKET_HDR);
- if (notSame(aePref,CameraSettings.KEY_AE_BRACKET_HDR,"Off")) {
+ if (aePref != null && notSame(aePref,CameraSettings.KEY_AE_BRACKET_HDR,"Off")) {
RotateTextToast.makeText(mActivity,
R.string.flash_aebracket_message,Toast.LENGTH_SHORT).show();
}
@@ -1465,13 +1481,12 @@ public class PhotoMenu extends MenuController
}
}
- String chromaFlashOn = mActivity.getString(R.string.
- pref_camera_advanced_feature_value_chromaflash_on);
- if (notSame(pref, CameraSettings.KEY_SCENE_MODE, Parameters.SCENE_MODE_AUTO)) {
+ String chromaFlashOn = mActivity.getString(R.string
+ .pref_camera_advanced_feature_value_chromaflash_on);
+ if (notSame(pref, CameraSettings.KEY_SCENE_MODE, chromaFlashOn)) {
ListPreference lp = mPreferenceGroup
.findPreference(CameraSettings.KEY_ADVANCED_FEATURES);
if (lp != null && chromaFlashOn.equals(lp.getValue())) {
- setPreference(CameraSettings.KEY_QC_CHROMA_FLASH, mSettingOff);
setPreference(CameraSettings.KEY_ADVANCED_FEATURES,
mActivity.getString(R.string.pref_camera_advanced_feature_default));
}
@@ -1495,7 +1510,10 @@ public class PhotoMenu extends MenuController
} else {
mHdrSwitcher.setVisibility(View.VISIBLE);
}
- updateFilterModeIcon(pref, pref);
+
+ ListPreference hdrPref = mPreferenceGroup.findPreference(CameraSettings.KEY_CAMERA_HDR);
+ ListPreference scenePref = mPreferenceGroup.findPreference(CameraSettings.KEY_SCENE_MODE);
+ updateFilterModeIcon(scenePref, hdrPref);
if (same(pref, CameraSettings.KEY_RECORD_LOCATION, "on")) {
mActivity.requestLocationPermission();
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index f3c57cb71..06c7cf619 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013-2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,12 +63,12 @@ import android.view.SurfaceHolder;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
-import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.camera.app.CameraApp;
import com.android.camera.CameraManager.CameraAFCallback;
import com.android.camera.CameraManager.CameraAFMoveCallback;
import com.android.camera.CameraManager.CameraPictureCallback;
@@ -104,6 +105,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Arrays;
import java.lang.NumberFormatException;
import java.util.List;
import java.util.Vector;
@@ -113,8 +115,6 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.SystemProperties;
-import java.util.Collections;
-import java.util.Formatter;
public class PhotoModule
implements CameraModule,
@@ -130,13 +130,14 @@ public class PhotoModule
private static final String TAG = "CAM_PhotoModule";
//QCom data members
- public static boolean mBrightnessVisible = false;
private static final int MAX_SHARPNESS_LEVEL = 6;
private boolean mRestartPreview = false;
private int mSnapshotMode;
private int mBurstSnapNum = 1;
private int mReceivedSnapNum = 0;
+ private int mLongshotSnapNum = 0;
public boolean mFaceDetectionEnabled = false;
+ private boolean mLgeHdrMode = false;
private DrawAutoHDR mDrawAutoHDR;
/*Histogram variables*/
private GraphView mGraphView;
@@ -159,6 +160,8 @@ public class PhotoModule
private static final int SET_PHOTO_UI_PARAMS = 11;
private static final int SWITCH_TO_GCAM_MODULE = 12;
private static final int ON_PREVIEW_STARTED = 13;
+ private static final int UNLOCK_CAM_SHUTTER = 14;
+ private static final int SET_FOCUS_RATIO = 15;
// The subset of parameters we need to update in setCameraParameters().
private static final int UPDATE_PARAM_INITIALIZE = 1;
@@ -204,7 +207,6 @@ public class PhotoModule
private boolean mAeLockSupported;
private boolean mAwbLockSupported;
private boolean mContinuousFocusSupported;
- private boolean mTouchAfAecFlag;
private boolean mLongshotSave = false;
private boolean mRefocus = false;
private boolean mLastPhotoTakenWithRefocus = false;
@@ -224,12 +226,9 @@ public class PhotoModule
private static final boolean PERSIST_SKIP_MEM_CHECK = PersistUtil.isSkipMemoryCheckEnabled();
- private static final int MINIMUM_BRIGHTNESS = 0;
- private static final int MAXIMUM_BRIGHTNESS = 6;
- private static final int DEFAULT_BRIGHTNESS = 3;
- private int mbrightness = 3;
- private int mbrightness_step = 1;
- private ProgressBar brightnessProgressBar;
+ private static final String PERSIST_LONGSHOT_MAX_SNAP = "persist.camera.longshot.max";
+ private static int mLongShotMaxSnap = -1;
+
// Constant from android.hardware.Camera.Parameters
private static final String KEY_PICTURE_FORMAT = "picture-format";
private SeekBar mBlurDegreeProgressBar;
@@ -265,6 +264,8 @@ public class PhotoModule
private byte[] mLastJpegData;
private int mLastJpegOrientation = 0;
+ private static Context mApplicationContext = null;
+
private Runnable mDoSnapRunnable = new Runnable() {
@Override
public void run() {
@@ -303,6 +304,7 @@ public class PhotoModule
private boolean mMirror;
private boolean mFirstTimeInitialized;
private boolean mIsImageCaptureIntent;
+ private int mOrientationOffset;
private int mCameraState = INIT;
private boolean mSnapshotOnIdle = false;
@@ -346,7 +348,6 @@ public class PhotoModule
private FocusOverlayManager mFocusManager;
private String mSceneMode;
- private String mCurrTouchAfAec = ParametersWrapper.TOUCH_AF_AEC_ON;
private String mSavedFlashMode = null;
private final Handler mHandler = new MainHandler();
@@ -537,8 +538,6 @@ public class PhotoModule
case SET_PHOTO_UI_PARAMS: {
setCameraParametersWhenIdle(UPDATE_PARAM_PREFERENCE);
- mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup,
- mPreferences);
break;
}
@@ -551,6 +550,16 @@ public class PhotoModule
onPreviewStarted();
break;
}
+
+ case UNLOCK_CAM_SHUTTER: {
+ mUI.enableShutter(true);
+ break;
+ }
+
+ case SET_FOCUS_RATIO: {
+ mUI.getFocusRing().setRadiusRatio((Float)msg.obj);
+ break;
+ }
}
}
}
@@ -570,6 +579,7 @@ public class PhotoModule
public void init(CameraActivity activity, View parent) {
mActivity = activity;
mRootView = parent;
+ mOrientationOffset = CameraUtil.isDefaultToPortrait(mActivity) ? 0 : 90;
mPreferences = ComboPreferences.get(mActivity);
if (mPreferences == null) {
mPreferences = new ComboPreferences(mActivity);
@@ -579,6 +589,7 @@ public class PhotoModule
mCameraId = getPreferredCameraId(mPreferences);
mContentResolver = mActivity.getContentResolver();
+ mApplicationContext = CameraApp.getContext();
// Surface texture is from camera screen nail and startPreview needs it.
// This must be done before startPreview.
@@ -588,6 +599,13 @@ public class PhotoModule
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
mUI = new PhotoUI(activity, this, parent);
+
+ // Power shutter
+ mActivity.initPowerShutter(mPreferences);
+
+ // Max brightness
+ mActivity.initMaxBrightness(mPreferences);
+
if (mOpenCameraThread == null) {
mOpenCameraThread = new OpenCameraThread();
mOpenCameraThread.start();
@@ -597,22 +615,16 @@ public class PhotoModule
mLocationManager = new LocationManager(mActivity, this);
mSensorManager = (SensorManager)(mActivity.getSystemService(Context.SENSOR_SERVICE));
- brightnessProgressBar = (ProgressBar)mRootView.findViewById(R.id.progress);
mBlurDegreeProgressBar = (SeekBar)mRootView.findViewById(R.id.blur_degree_bar);
mBlurDegreeProgressBar.setOnSeekBarChangeListener(mBlurDegreeListener);
mBlurDegreeProgressBar.setMax(100);
- if (brightnessProgressBar instanceof SeekBar) {
- SeekBar seeker = (SeekBar) brightnessProgressBar;
- seeker.setOnSeekBarChangeListener(mSeekListener);
- }
- brightnessProgressBar.setMax(MAXIMUM_BRIGHTNESS);
- mbrightness = mPreferences.getInt(
- CameraSettings.KEY_BRIGHTNESS,
- DEFAULT_BRIGHTNESS);
- brightnessProgressBar.setProgress(mbrightness);
- brightnessProgressBar.setVisibility(View.INVISIBLE);
Storage.setSaveSDCard(
mPreferences.getString(CameraSettings.KEY_CAMERA_SAVEPATH, "0").equals("1"));
+
+ // LGE HDR mode
+ if (mApplicationContext != null) {
+ mLgeHdrMode = mApplicationContext.getResources().getBoolean(R.bool.lge_hdr_mode);
+ }
}
private void initializeControlByIntent() {
@@ -637,7 +649,7 @@ public class PhotoModule
// camera only
private void locationFirstRun() {
boolean enableRecordingLocation = false;
- if (mActivity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
+ if (mActivity.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
enableRecordingLocation = true;
}
@@ -735,7 +747,7 @@ public class PhotoModule
Log.v(TAG, "onCameraOpened");
openCameraCommon();
resizeForPreviewAspectRatio();
- updateFocusManager(mUI);
+ mFocusManager.setFocusRing(mUI.getFocusRing());
}
private void switchCamera() {
@@ -759,7 +771,6 @@ public class PhotoModule
}
closeCamera();
mUI.collapseCameraControls();
- mUI.clearFaces();
if (mFocusManager != null) mFocusManager.removeMessages();
// Restart the camera and initialize the UI. From onCreate.
@@ -776,8 +787,8 @@ public class PhotoModule
mParameters = mCameraDevice.getParameters();
mInitialParams = mCameraDevice.getParameters();
initializeCapabilities();
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
- mMirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
+ CameraHolder.CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+ mMirror = (info.facing == CameraHolder.CameraInfo.CAMERA_FACING_FRONT);
mFocusManager.setMirror(mMirror);
mFocusManager.setParameters(mInitialParams);
setupPreview();
@@ -871,8 +882,6 @@ public class PhotoModule
mUI.setPreference(CameraSettings.KEY_ZSL, ParametersWrapper.ZSL_OFF);
mUI.setPreference(CameraSettings.KEY_FACE_DETECTION,
ParametersWrapper.FACE_DETECTION_OFF);
- mUI.setPreference(CameraSettings.KEY_TOUCH_AF_AEC,
- ParametersWrapper.TOUCH_AF_AEC_OFF);
mUI.setPreference(CameraSettings.KEY_FOCUS_MODE,
Parameters.FOCUS_MODE_AUTO);
mUI.setPreference(CameraSettings.KEY_FLASH_MODE,
@@ -884,7 +893,7 @@ public class PhotoModule
}
void setPreviewFrameLayoutCameraOrientation(){
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+ CameraHolder.CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
//if camera mount angle is 0 or 180, we want to resize preview
if (info.orientation % 180 == 0){
mUI.cameraOrientationPreviewResize(true);
@@ -1013,9 +1022,9 @@ public class PhotoModule
|| mFaceDetectionStarted || mCameraState != IDLE) return;
if (mParameters.getMaxNumDetectedFaces() > 0) {
mFaceDetectionStarted = true;
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+ CameraHolder.CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
mUI.onStartFaceDetection(mDisplayOrientation,
- (info.facing == CameraInfo.CAMERA_FACING_FRONT));
+ (info.facing == CameraHolder.CameraInfo.CAMERA_FACING_FRONT));
mCameraDevice.setFaceDetectionCallback(mHandler, mUI);
mCameraDevice.startFaceDetection();
}
@@ -1027,12 +1036,19 @@ public class PhotoModule
if (mParameters.getMaxNumDetectedFaces() > 0) {
mFaceDetectionStarted = false;
mCameraDevice.setFaceDetectionCallback(null, null);
- mUI.pauseFaceDetection();
mCameraDevice.stopFaceDetection();
mUI.onStopFaceDetection();
}
}
+ @Override
+ public void setFocusRatio(float ratio) {
+ mHandler.removeMessages(SET_FOCUS_RATIO);
+ Message m = mHandler.obtainMessage(SET_FOCUS_RATIO);
+ m.obj = ratio;
+ mHandler.sendMessage(m);
+ }
+
// TODO: need to check cached background apps memory and longshot ION memory
private boolean isLongshotNeedCancel() {
@@ -1076,6 +1092,11 @@ public class PhotoModule
private final class LongshotShutterCallback
implements CameraShutterCallback {
+ private int mExpectedLongshotSnapNum;
+
+ public LongshotShutterCallback() {
+ mExpectedLongshotSnapNum = mLongshotSnapNum;
+ }
@Override
public void onShutter(CameraProxy camera) {
@@ -1083,9 +1104,21 @@ public class PhotoModule
mShutterLag = mShutterCallbackTime - mCaptureStartTime;
Log.e(TAG, "[KPI Perf] PROFILE_SHUTTER_LAG mShutterLag = " + mShutterLag + "ms");
synchronized(mCameraDevice) {
+ if (mExpectedLongshotSnapNum != mLongshotSnapNum) {
+ return;
+ }
+
+ if (++mLongshotSnapNum >= mLongShotMaxSnap &&
+ (mLongShotMaxSnap != -1)) {
+ mLongshotActive = false;
+ mUI.enableShutter(false);
+ mCameraDevice.stopLongshot();
+ return;
+ }
if (mCameraState != LONGSHOT ||
!mLongshotActive) {
+ mCameraDevice.stopLongshot();
return;
}
@@ -1098,8 +1131,6 @@ public class PhotoModule
return;
}
- mUI.doShutterAnimation();
-
Location loc = getLocationAccordPictureFormat(mParameters.get(KEY_PICTURE_FORMAT));
mLongShotCaptureCount++;
@@ -1212,6 +1243,7 @@ public class PhotoModule
implements CameraPictureCallback {
@Override
public void onPictureTaken(byte [] data, CameraProxy camera) {
+ Log.d(TAG, "PostViewPictureCallback: onPictureTaken()");
mPostViewPictureCallbackTime = System.currentTimeMillis();
Log.v(TAG, "mShutterToPostViewCallbackTime = "
+ (mPostViewPictureCallbackTime - mShutterCallbackTime)
@@ -1223,6 +1255,7 @@ public class PhotoModule
implements CameraPictureCallback {
@Override
public void onPictureTaken(byte [] rawData, CameraProxy camera) {
+ Log.d(TAG, "RawPictureCallback: onPictureTaken()");
mRawPictureCallbackTime = System.currentTimeMillis();
Log.v(TAG, "mShutterToRawCallbackTime = "
+ (mRawPictureCallbackTime - mShutterCallbackTime) + "ms");
@@ -1238,12 +1271,11 @@ public class PhotoModule
@Override
public void onPictureTaken(final byte [] jpegData, CameraProxy camera) {
+ Log.d(TAG, "LongshotPictureCallback: onPictureTaken()");
if (mPaused) {
return;
}
- mFocusManager.updateFocusUI(); // Ensure focus indicator is hidden.
-
String jpegFilePath = new String(jpegData);
mNamedImages.nameNewImage(mCaptureStartTime);
NamedEntity name = mNamedImages.getNextNameEntity();
@@ -1330,8 +1362,12 @@ public class PhotoModule
@Override
public void onPictureTaken(byte [] jpegData, CameraProxy camera) {
+ String focusMode;
+
mUI.stopSelfieFlash();
- mUI.enableShutter(true);
+ if (mCameraState != LONGSHOT) {
+ mUI.enableShutter(true);
+ }
if (mUI.isPreviewCoverVisible()) {
// When take picture request is sent before starting preview, onPreviewFrame()
// callback doesn't happen so removing preview cover here, instead.
@@ -1353,14 +1389,29 @@ public class PhotoModule
mUI.setSwipingEnabled(true);
}
+ ExifInterface exif = Exif.getExif(jpegData);
+ boolean overrideMakerAndModelTag = false;
+ if (mApplicationContext != null) {
+ overrideMakerAndModelTag =
+ mApplicationContext.getResources()
+ .getBoolean(R.bool.override_maker_and_model_tag);
+ }
+
+ if (overrideMakerAndModelTag) {
+ ExifTag maker = exif.buildTag(ExifInterface.TAG_MAKE, Build.MANUFACTURER);
+ exif.setTag(maker);
+ ExifTag model = exif.buildTag(ExifInterface.TAG_MODEL, Build.MODEL);
+ exif.setTag(model);
+ }
+
mReceivedSnapNum = mReceivedSnapNum + 1;
mJpegPictureCallbackTime = System.currentTimeMillis();
if(mSnapshotMode == CameraInfoWrapper.CAMERA_SUPPORT_MODE_ZSL) {
Log.v(TAG, "JpegPictureCallback : in zslmode");
mParameters = mCameraDevice.getParameters();
- mBurstSnapNum = mParameters.getInt("num-snaps-per-shutter");
+ mBurstSnapNum = CameraUtil.getNumSnapsPerShutter(mParameters);
}
- Log.v(TAG, "JpegPictureCallback: Received = " + mReceivedSnapNum +
+ Log.v(TAG, "JpegPictureCallback: Received = " + mReceivedSnapNum + " " +
"Burst count = " + mBurstSnapNum);
// If postview callback has arrived, the captured image is displayed
// in postview callback. If not, the captured image is displayed in
@@ -1379,27 +1430,61 @@ public class PhotoModule
Log.v(TAG, "mPictureDisplayedToJpegCallbackTime = "
+ mPictureDisplayedToJpegCallbackTime + "ms");
- mFocusManager.updateFocusUI(); // Ensure focus indicator is hidden.
+ if (isLongshotDone()) {
+ mCameraDevice.setLongshot(false);
+ }
boolean needRestartPreview = !mIsImageCaptureIntent
&& !mPreviewRestartSupport
&& (mCameraState != LONGSHOT)
&& (mSnapshotMode != CameraInfoWrapper.CAMERA_SUPPORT_MODE_ZSL)
- && (mReceivedSnapNum == mBurstSnapNum);
+ && ((mReceivedSnapNum == mBurstSnapNum) && (mCameraState != LONGSHOT));
+
+ needRestartPreview |= (isLongshotDone() && !mFocusManager.isZslEnabled());
+ needRestartPreview |= mLgeHdrMode && (mCameraState != LONGSHOT);
+
+ CameraHolder.CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+
+ final boolean isAuxCamera = info.facing > CameraHolder.CameraInfo.CAMERA_FACING_FRONT;
+ final boolean isBackCamera =
+ info.facing == CameraHolder.CameraInfo.CAMERA_FACING_BACK;
+ final boolean isFrontCamera =
+ info.facing == CameraHolder.CameraInfo.CAMERA_FACING_FRONT;
+ boolean auxCameraRestartPreviewOnPictureTaken = false;
+ boolean backCameraRestartPreviewOnPictureTaken = false;
+ boolean frontCameraRestartPreviewOnPictureTaken = false;
+ if (mApplicationContext != null) {
+ auxCameraRestartPreviewOnPictureTaken = mApplicationContext.getResources()
+ .getBoolean(R.bool.additional_camera_restart_preview_onPictureTaken);
+ backCameraRestartPreviewOnPictureTaken = mApplicationContext.getResources()
+ .getBoolean(R.bool.back_camera_restart_preview_onPictureTaken);
+ frontCameraRestartPreviewOnPictureTaken = mApplicationContext.getResources()
+ .getBoolean(R.bool.front_camera_restart_preview_onPictureTaken);
+ }
+
+ if ((isAuxCamera && auxCameraRestartPreviewOnPictureTaken ||
+ isBackCamera && backCameraRestartPreviewOnPictureTaken ||
+ isFrontCamera && frontCameraRestartPreviewOnPictureTaken) &&
+ mCameraState != LONGSHOT) {
+ needRestartPreview = true;
+ }
+
if (needRestartPreview) {
+ Log.d(TAG, "JpegPictureCallback: needRestartPreview");
setupPreview();
- if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(
- mFocusManager.getFocusMode())) {
+ focusMode = mFocusManager.getFocusMode(false);
+ if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(focusMode) ||
+ CameraUtil.FOCUS_MODE_MW_CONTINUOUS_PICTURE.equals(focusMode)) {
mCameraDevice.cancelAutoFocus();
}
- } else if ((mReceivedSnapNum == mBurstSnapNum)
- && (mCameraState != LONGSHOT)){
- mFocusManager.resetTouchFocus();
- if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(
- mFocusManager.getFocusMode())) {
+ } else if (((mCameraState != LONGSHOT) && (mReceivedSnapNum == mBurstSnapNum))
+ || isLongshotDone()){
+ mFocusManager.restartTouchFocusTimer();
+ focusMode = mFocusManager.getFocusMode(false);
+ if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(focusMode) ||
+ CameraUtil.FOCUS_MODE_MW_CONTINUOUS_PICTURE.equals(focusMode)) {
mCameraDevice.cancelAutoFocus();
}
- mUI.resumeFaceDetection();
if (!mIsImageCaptureIntent) {
setCameraState(IDLE);
}
@@ -1419,14 +1504,12 @@ public class PhotoModule
}
}
if (!mRefocus || (mRefocus && mReceivedSnapNum == 7)) {
- ExifInterface exif = Exif.getExif(jpegData);
int orientation = Exif.getOrientation(exif);
if(mCameraId == CameraHolder.instance().getFrontCameraId()) {
IconListPreference selfieMirrorPref = (IconListPreference) mPreferenceGroup
.findPreference(CameraSettings.KEY_SELFIE_MIRROR);
if (selfieMirrorPref != null && selfieMirrorPref.getValue() != null &&
selfieMirrorPref.getValue().equalsIgnoreCase("enable")) {
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
jpegData = flipJpeg(jpegData, info.orientation, orientation);
jpegData = addExifTags(jpegData, orientation);
}
@@ -1498,7 +1581,8 @@ public class PhotoModule
}
}
// Animate capture with real jpeg data instead of a preview frame.
- if (mCameraState != LONGSHOT) {
+ if ((mCameraState != LONGSHOT) ||
+ isLongshotDone()) {
Size pic_size = mParameters.getPictureSize();
if ((pic_size.width <= 352) && (pic_size.height<= 288)) {
mUI.setDownFactor(2); //Downsample by 2 for CIF & below
@@ -1545,6 +1629,10 @@ public class PhotoModule
mJpegPictureCallbackTime = 0;
}
+ if (isLongshotDone()) {
+ mLongshotSnapNum = 0;
+ }
+
if (mHiston && (mSnapshotMode ==CameraInfoWrapper.CAMERA_SUPPORT_MODE_ZSL)) {
mActivity.runOnUiThread(new Runnable() {
public void run() {
@@ -1565,16 +1653,6 @@ public class PhotoModule
}
}
- private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
- public void onStartTrackingTouch(SeekBar bar) {
- // no support
- }
- public void onProgressChanged(SeekBar bar, int progress, boolean fromtouch) {
- }
- public void onStopTrackingTouch(SeekBar bar) {
- }
- };
-
private OnSeekBarChangeListener mBlurDegreeListener = new OnSeekBarChangeListener() {
public void onStartTrackingTouch(SeekBar bar) {
}
@@ -1610,6 +1688,8 @@ public class PhotoModule
setCameraState(IDLE);
break;
}
+ mCameraDevice.refreshParameters();
+ mFocusManager.setParameters(mCameraDevice.getParameters());
mFocusManager.onAutoFocus(focused, mUI.isShutterPressed());
}
}
@@ -1620,6 +1700,8 @@ public class PhotoModule
@Override
public void onAutoFocusMoving(
boolean moving, CameraProxy camera) {
+ mCameraDevice.refreshParameters();
+ mFocusManager.setParameters(mCameraDevice.getParameters());
mFocusManager.onAutoFocusMoving(moving);
}
}
@@ -1721,11 +1803,12 @@ public class PhotoModule
}
if (mCameraState == LONGSHOT) {
+ mLongshotSnapNum = 0;
mCameraDevice.setLongshot(true);
}
// Set rotation and gps data.
- int orientation = mOrientation;
+ int orientation = (mOrientation + mOrientationOffset) % 360;
mJpegRotation = CameraUtil.getJpegRotation(mCameraId, orientation);
String pictureFormat = mParameters.get(KEY_PICTURE_FORMAT);
Location loc = getLocationAccordPictureFormat(pictureFormat);
@@ -1753,11 +1836,14 @@ public class PhotoModule
mParameters = mCameraDevice.getParameters();
}
- try {
- mBurstSnapNum = mParameters.getInt("num-snaps-per-shutter");
- }catch (NumberFormatException ex){
- mBurstSnapNum = 1;
+ // LGE G4: Disable HDR if luminance is low and flash gets used
+ if (CameraUtil.isLowLuminance(mParameters)) {
+ mParameters.set(CameraSettings.KEY_SNAPCAM_HDR_MODE, CameraSettings.LGE_HDR_MODE_OFF);
+ mCameraDevice.setParameters(mParameters);
+ mParameters = mCameraDevice.getParameters();
}
+
+ mBurstSnapNum = CameraUtil.getNumSnapsPerShutter(mParameters);
mReceivedSnapNum = 0;
mPreviewRestartSupport = PersistUtil.isPreviewRestartEnabled();
mPreviewRestartSupport &= CameraSettings.isInternalPreviewSupported(
@@ -1768,10 +1854,12 @@ public class PhotoModule
mPreviewRestartSupport &= PIXEL_FORMAT_JPEG.equalsIgnoreCase(
pictureFormat);
+ mUI.enableShutter(false);
+
// We don't want user to press the button again while taking a
// multi-second HDR photo. For longshot, no need to disable.
- if (mCameraState != LONGSHOT) {
- mUI.enableShutter(false);
+ if (!CameraUtil.SCENE_MODE_HDR.equals(mSceneMode)) {
+ mHandler.sendEmptyMessageDelayed(UNLOCK_CAM_SHUTTER, 120);
}
if (!isShutterSoundOn()) {
@@ -1801,6 +1889,17 @@ public class PhotoModule
mRawPictureCallback, mPostViewPictureCallback,
new JpegPictureCallback(loc));
setCameraState(SNAPSHOT_IN_PROGRESS);
+
+ // LGE G4: Preview needs to be restarted when flash gets used
+ if (CameraUtil.isSupported(mParameters, CameraSettings.KEY_LUMINANCE_CONDITION)) {
+ String flashMode = mPreferences.getString(CameraSettings.KEY_FLASH_MODE,
+ mActivity.getString(R.string.pref_camera_flashmode_default));
+ if (flashMode.equals(Parameters.FLASH_MODE_ON) ||
+ (!flashMode.equals(Parameters.FLASH_MODE_OFF) &&
+ CameraUtil.isLowLuminance(mParameters))) {
+ setupPreview();
+ }
+ }
}
mNamedImages.nameNewImage(mCaptureStartTime, mRefocus);
@@ -1838,8 +1937,26 @@ public class PhotoModule
}
}
+ private void updateLongshotScene() {
+ String[] longshotScenes = mActivity.getResources().getStringArray(
+ R.array.longshot_scenemodes);
+ if (longshotScenes.length == 0) {
+ mUI.overrideSettings(CameraSettings.KEY_LONGSHOT, null);
+ return;
+ }
+ boolean useLongshot = false;
+ for (String scene : longshotScenes) {
+ if (scene.equals(mSceneMode)) {
+ useLongshot = true;
+ break;
+ }
+ }
+ mUI.overrideSettings(CameraSettings.KEY_LONGSHOT,
+ useLongshot ? mActivity.getString(R.string.setting_on_value) :
+ mActivity.getString(R.string.setting_off_value));
+ }
+
private void updateCommonManual3ASettings() {
- String touchAfAec = ParametersWrapper.TOUCH_AF_AEC_OFF;
mSceneMode = Parameters.SCENE_MODE_AUTO;
String flashMode = Parameters.FLASH_MODE_OFF;
String redeyeReduction = mActivity.getString(R.string.
@@ -1851,27 +1968,25 @@ public class PhotoModule
String exposureCompensation = CameraSettings.EXPOSURE_DEFAULT_VALUE;
if (mManual3AEnabled > 0) {
overrideCameraSettings(flashMode, null, null,
- exposureCompensation, touchAfAec,
+ exposureCompensation,
ParametersWrapper.getAutoExposure(mParameters),
- Integer.toString(ParametersWrapper.getSaturation(mParameters)),
- Integer.toString(ParametersWrapper.getContrast(mParameters)),
- Integer.toString(ParametersWrapper.getSharpness(mParameters)),
+ getSaturationSafe(),
+ getContrastSafe(),
+ getSharpnessSafe(),
colorEffect,
mSceneMode, redeyeReduction, aeBracketing);
mUI.overrideSettings(CameraSettings.KEY_LONGSHOT,
mActivity.getString(R.string.setting_off_value));
} else {
//enable all
- touchAfAec = mActivity.getString(
- R.string.pref_camera_touchafaec_default);
overrideCameraSettings(null, null, null,
- null, touchAfAec, null,
+ null, null,
null, null, null, null,
null, null, null);
mUI.overrideSettings(CameraSettings.KEY_LONGSHOT, null);
}
- String isoMode = ParametersWrapper.getISOValue(mParameters);
+ String isoMode = CameraSettings.getISOValue(mParameters);
final String isoManual = CameraSettings.KEY_MANUAL_ISO;
if (isoMode.equals(isoManual)) {
final String isoPref = mPreferences.getString(
@@ -1887,7 +2002,7 @@ public class PhotoModule
}
if ((mManual3AEnabled & MANUAL_FOCUS) != 0) {
mUI.overrideSettings(CameraSettings.KEY_FOCUS_MODE,
- mFocusManager.getFocusMode());
+ mFocusManager.getFocusMode(false));
}
}
@@ -1899,7 +2014,6 @@ public class PhotoModule
String focusMode = null;
String colorEffect = null;
String exposureCompensation = null;
- String touchAfAec = null;
boolean disableLongShot = false;
String ubiFocusOn = mActivity.getString(R.string.
@@ -1965,8 +2079,10 @@ public class PhotoModule
(fssr != null && fssr.equals(fssrOn)) ||
(truePortrait != null && truePortrait.equals(truPortraitOn)) ||
(stillMore != null && stillMore.equals(stillMoreOn))) {
- if ( (optiZoom != null && optiZoom.equals(optiZoomOn)) ||
- (reFocus != null && reFocus.equals(reFocusOn)) ) {
+ if ((optiZoom != null && optiZoom.equals(optiZoomOn)) ||
+ (reFocus != null && reFocus.equals(reFocusOn)) ||
+ (CameraSettings.hasChromaFlashScene(mActivity) &&
+ chromaFlash != null && chromaFlash.equals(chromaFlashOn))) {
sceneMode = null;
} else {
mSceneMode = sceneMode = Parameters.SCENE_MODE_AUTO;
@@ -1982,7 +2098,7 @@ public class PhotoModule
exposureCompensation = CameraSettings.EXPOSURE_DEFAULT_VALUE;
overrideCameraSettings(null, null, focusMode,
- exposureCompensation, touchAfAec, null,
+ exposureCompensation, null,
null, null, null, colorEffect,
sceneMode, redeyeReduction, aeBracketing);
disableLongShot = true;
@@ -1990,10 +2106,11 @@ public class PhotoModule
// If scene mode is set, for white balance and focus mode
// read settings from preferences so we retain user preferences.
- if (!Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) {
+ if (!Parameters.SCENE_MODE_AUTO.equals(mSceneMode) &&
+ !"asd".equals(mSceneMode) && !"sports".equals(mSceneMode)) {
flashMode = Parameters.FLASH_MODE_OFF;
String whiteBalance = Parameters.WHITE_BALANCE_AUTO;
- focusMode = mFocusManager.getFocusMode();
+ focusMode = mFocusManager.getFocusMode(false);
colorEffect = mParameters.getColorEffect();
String defaultEffect = mActivity.getString(R.string.pref_camera_coloreffect_default);
if (CameraUtil.SCENE_MODE_HDR.equals(mSceneMode)) {
@@ -2011,20 +2128,19 @@ public class PhotoModule
}
exposureCompensation =
Integer.toString(mParameters.getExposureCompensation());
- touchAfAec = mCurrTouchAfAec;
overrideCameraSettings(null, whiteBalance, focusMode,
- exposureCompensation, touchAfAec,
+ exposureCompensation,
ParametersWrapper.getAutoExposure(mParameters),
- Integer.toString(ParametersWrapper.getSaturation(mParameters)),
- Integer.toString(ParametersWrapper.getContrast(mParameters)),
- Integer.toString(ParametersWrapper.getSharpness(mParameters)),
+ getSaturationSafe(),
+ getContrastSafe(),
+ getSharpnessSafe(),
colorEffect,
sceneMode, redeyeReduction, aeBracketing);
} else if (mFocusManager.isZslEnabled()) {
focusMode = mParameters.getFocusMode();
overrideCameraSettings(null, null, focusMode,
- exposureCompensation, touchAfAec, null,
+ exposureCompensation, null,
null, null, null, colorEffect,
sceneMode, redeyeReduction, aeBracketing);
} else {
@@ -2032,7 +2148,7 @@ public class PhotoModule
updateCommonManual3ASettings();
} else {
overrideCameraSettings(null, null, focusMode,
- exposureCompensation, touchAfAec, null,
+ exposureCompensation, null,
null, null, null, colorEffect,
sceneMode, redeyeReduction, aeBracketing);
}
@@ -2043,11 +2159,17 @@ public class PhotoModule
flashMode = Parameters.FLASH_MODE_OFF;
mParameters.setFlashMode(flashMode);
}
+
+ if (chromaFlash != null && chromaFlash.equals(chromaFlashOn)) {
+ flashMode = Parameters.FLASH_MODE_ON;
+ mParameters.setFlashMode(flashMode);
+ }
+
if (disableLongShot) {
mUI.overrideSettings(CameraSettings.KEY_LONGSHOT,
mActivity.getString(R.string.setting_off_value));
} else {
- mUI.overrideSettings(CameraSettings.KEY_LONGSHOT, null);
+ updateLongshotScene();
}
if(TsMakeupManager.HAS_TS_MAKEUP) {
@@ -2093,17 +2215,16 @@ public class PhotoModule
private void overrideCameraSettings(final String flashMode,
final String whiteBalance, final String focusMode,
- final String exposureMode, final String touchMode,
- final String autoExposure, final String saturation,
- final String contrast, final String sharpness,
- final String coloreffect, final String sceneMode,
- final String redeyeReduction, final String aeBracketing) {
+ final String exposureMode, final String autoExposure,
+ final String saturation, final String contrast,
+ final String sharpness, final String coloreffect,
+ final String sceneMode, final String redeyeReduction,
+ final String aeBracketing) {
mUI.overrideSettings(
CameraSettings.KEY_FLASH_MODE, flashMode,
CameraSettings.KEY_WHITE_BALANCE, whiteBalance,
CameraSettings.KEY_FOCUS_MODE, focusMode,
CameraSettings.KEY_EXPOSURE, exposureMode,
- CameraSettings.KEY_TOUCH_AF_AEC, touchMode,
CameraSettings.KEY_AUTOEXPOSURE, autoExposure,
CameraSettings.KEY_SATURATION, saturation,
CameraSettings.KEY_CONTRAST, contrast,
@@ -2119,7 +2240,7 @@ public class PhotoModule
mCameraId, CameraHolder.instance().getCameraInfo());
mPreferenceGroup = settings.getPreferenceGroup(R.xml.camera_preferences);
- int numOfCams = Camera.getNumberOfCameras();
+ int numOfCams = CameraHolder.instance().getNumberOfCameras();
Log.e(TAG,"loadCameraPreferences() updating camera_id pref");
@@ -2137,8 +2258,8 @@ public class PhotoModule
int[] largeIconIds = new int[numOfCams];
for(int i=0;i<numOfCams;i++) {
- CameraInfo info = CameraHolder.instance().getCameraInfo()[i];
- if(info.facing == CameraInfo.CAMERA_FACING_BACK) {
+ CameraHolder.CameraInfo info = CameraHolder.instance().getCameraInfo()[i];
+ if(info.facing == CameraHolder.CameraInfo.CAMERA_FACING_BACK) {
iconIds[i] = R.drawable.ic_switch_back;
entries[i] = mActivity.getResources().getString(R.string.pref_camera_id_entry_back);
labels[i] = mActivity.getResources().getString(R.string.pref_camera_id_label_back);
@@ -2164,6 +2285,7 @@ public class PhotoModule
// the camera then point the camera to floor or sky, we still have
// the correct orientation.
if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) return;
+ orientation = (orientation - mOrientationOffset + 360) % 360;
int oldOrientation = mOrientation;
mOrientation = CameraUtil.roundOrientation(orientation, mOrientation);
if (oldOrientation != mOrientation) {
@@ -2314,20 +2436,7 @@ public class PhotoModule
synchronized(mCameraDevice) {
if (mCameraState == LONGSHOT) {
mLongshotActive = false;
- mCameraDevice.setLongshot(false);
- mUI.animateCapture(mLastJpegData);
- mLastJpegData = null;
- if (!mFocusManager.isZslEnabled()) {
- setupPreview();
- } else {
- setCameraState(IDLE);
- mFocusManager.resetTouchFocus();
- if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(
- mFocusManager.getFocusMode())) {
- mCameraDevice.cancelAutoFocus();
- }
- mUI.resumeFaceDetection();
- }
+ mUI.enableShutter(false);
}
}
@@ -2487,6 +2596,7 @@ public class PhotoModule
@Override
public void onResumeBeforeSuper() {
mPaused = false;
+ if (mFocusManager == null) initializeFocusManager();
}
private void openCamera() {
@@ -2596,8 +2706,6 @@ public class PhotoModule
}
mUI.initDisplayChangeListener();
keepScreenOnAwhile();
- mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup,
- mPreferences);
UsageStatistics.onContentViewChanged(
UsageStatistics.COMPONENT_CAMERA, "PhotoModule");
@@ -2672,6 +2780,12 @@ public class PhotoModule
// (e.g. onResume -> onPause -> onResume).
stopPreview();
+ // Load the power shutter
+ mActivity.initPowerShutter(mPreferences);
+
+ // Load max brightness
+ mActivity.initMaxBrightness(mPreferences);
+
mNamedImages = null;
if (mLocationManager != null) mLocationManager.recordLocation(false);
@@ -2708,29 +2822,17 @@ public class PhotoModule
if (mFocusManager != null) {
mFocusManager.removeMessages();
} else {
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
- mMirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
+ CameraHolder.CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+ mMirror = (info.facing == CameraHolder.CameraInfo.CAMERA_FACING_FRONT);
String[] defaultFocusModes = mActivity.getResources().getStringArray(
R.array.pref_camera_focusmode_default_array);
- mFocusManager = new FocusOverlayManager(mPreferences, defaultFocusModes,
- mInitialParams, this, mMirror,
- mActivity.getMainLooper(), mUI);
- }
- }
-
- private void updateFocusManager(PhotoUI mUI) {
- // Idea here is to let focus manager create in camera open thread
- // (in initializeFocusManager) even if photoUI is null by that time so
- // as to not block start preview process. Once UI creation is done,
- // we will update focus manager with proper UI.
- if (mFocusManager != null && mUI != null) {
- mFocusManager.setPhotoUI(mUI);
-
- View root = mUI.getRootView();
- // These depend on camera parameters.
- int width = root.getWidth();
- int height = root.getHeight();
- mFocusManager.setPreviewSize(width, height);
+ synchronized (this) {
+ if (mFocusManager == null) {
+ mFocusManager = new FocusOverlayManager(mPreferences, defaultFocusModes,
+ mInitialParams, this, mMirror,
+ mActivity.getMainLooper(), mUI.getFocusRing(), mActivity);
+ }
+ }
}
}
@@ -2791,6 +2893,7 @@ public class PhotoModule
if (null != mCameraDevice ) {
mCameraDevice.cancelAutoFocus();
setCameraState(IDLE);
+ mFocusManager.setAeAwbLock(false);
setCameraParameters(UPDATE_PARAM_PREFERENCE);
}
}
@@ -2804,13 +2907,8 @@ public class PhotoModule
|| mCameraState == PREVIEW_STOPPED) {
return;
}
- //If Touch AF/AEC is disabled in UI, return
- if(this.mTouchAfAecFlag == false) {
- return;
- }
// Check if metering area or focus area is supported.
if (!mFocusAreaSupported && !mMeteringAreaSupported) return;
- if (! mFocusManager.getPreviewRect().contains(x, y)) return;
mFocusManager.onSingleTapUp(x, y);
}
@@ -2821,14 +2919,34 @@ public class PhotoModule
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
+ // Do not handle any key if the activity is
+ // not in active camera/video mode
+ if (!mActivity.isInCameraApp()) {
+ return false;
+ }
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_MEDIA_NEXT:
+ if (mFirstTimeInitialized && (mUI.mMenuInitialized)) {
+ if (!CameraActivity.mPowerShutter && !CameraUtil.hasCameraKey()) {
+ onShutterButtonFocus(true);
+ } else {
+ mUI.onScaleStepResize(true);
+ }
+ }
+ return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
- if (CameraUtil.volumeKeyShutterDisable(mActivity)) {
- return false;
+ case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+ if (mFirstTimeInitialized && (mUI.mMenuInitialized)) {
+ if (!CameraActivity.mPowerShutter && !CameraUtil.hasCameraKey()) {
+ onShutterButtonFocus(true);
+ } else {
+ mUI.onScaleStepResize(false);
+ }
}
+ return true;
case KeyEvent.KEYCODE_FOCUS:
- if (/*TODO: mActivity.isInCameraApp() &&*/ mFirstTimeInitialized) {
+ if (mFirstTimeInitialized) {
if (event.getRepeatCount() == 0) {
onShutterButtonFocus(true);
}
@@ -2836,52 +2954,11 @@ public class PhotoModule
}
return false;
case KeyEvent.KEYCODE_CAMERA:
+ case KeyEvent.KEYCODE_HEADSETHOOK:
if (mFirstTimeInitialized && event.getRepeatCount() == 0) {
onShutterButtonClick();
}
return true;
- case KeyEvent.KEYCODE_DPAD_LEFT:
- if ( (mCameraState != PREVIEW_STOPPED) && (mFocusManager != null) &&
- (mFocusManager.getCurrentFocusState() != mFocusManager.STATE_FOCUSING) &&
- (mFocusManager.getCurrentFocusState() != mFocusManager.STATE_FOCUSING_SNAP_ON_FINISH) ) {
- if (mbrightness > MINIMUM_BRIGHTNESS) {
- mbrightness-=mbrightness_step;
- synchronized (mCameraDevice) {
- /* Set the "luma-adaptation" parameter */
- mParameters = mCameraDevice.getParameters();
- mParameters.set("luma-adaptation", String.valueOf(mbrightness));
- mCameraDevice.setParameters(mParameters);
- }
- }
- brightnessProgressBar.setProgress(mbrightness);
- Editor editor = mPreferences.edit();
- editor.putInt(CameraSettings.KEY_BRIGHTNESS, mbrightness);
- editor.apply();
- brightnessProgressBar.setVisibility(View.INVISIBLE);
- mBrightnessVisible = true;
- }
- break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- if ( (mCameraState != PREVIEW_STOPPED) && (mFocusManager != null) &&
- (mFocusManager.getCurrentFocusState() != mFocusManager.STATE_FOCUSING) &&
- (mFocusManager.getCurrentFocusState() != mFocusManager.STATE_FOCUSING_SNAP_ON_FINISH) ) {
- if (mbrightness < MAXIMUM_BRIGHTNESS) {
- mbrightness+=mbrightness_step;
- synchronized (mCameraDevice) {
- /* Set the "luma-adaptation" parameter */
- mParameters = mCameraDevice.getParameters();
- mParameters.set("luma-adaptation", String.valueOf(mbrightness));
- mCameraDevice.setParameters(mParameters);
- }
- }
- brightnessProgressBar.setProgress(mbrightness);
- Editor editor = mPreferences.edit();
- editor.putInt(CameraSettings.KEY_BRIGHTNESS, mbrightness);
- editor.apply();
- brightnessProgressBar.setVisibility(View.INVISIBLE);
- mBrightnessVisible = true;
- }
- break;
case KeyEvent.KEYCODE_DPAD_CENTER:
// If we get a dpad center event without any focused view, move
// the focus to the shutter button and press it.
@@ -2893,6 +2970,12 @@ public class PhotoModule
mUI.pressShutterButton();
}
return true;
+ case KeyEvent.KEYCODE_POWER:
+ if (mFirstTimeInitialized && event.getRepeatCount() == 0
+ && CameraActivity.mPowerShutter && !CameraUtil.hasCameraKey()) {
+ onShutterButtonFocus(true);
+ }
+ return true;
}
return false;
}
@@ -2902,17 +2985,24 @@ public class PhotoModule
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
- if (/*mActivity.isInCameraApp() && */ mFirstTimeInitialized
- && !CameraUtil.volumeKeyShutterDisable(mActivity)) {
+ case KeyEvent.KEYCODE_MEDIA_NEXT:
+ case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+ if (!CameraActivity.mPowerShutter && !CameraUtil.hasCameraKey()
+ && mFirstTimeInitialized) {
onShutterButtonClick();
- return true;
}
- return false;
+ return true;
case KeyEvent.KEYCODE_FOCUS:
if (mFirstTimeInitialized) {
onShutterButtonFocus(false);
}
return true;
+ case KeyEvent.KEYCODE_POWER:
+ if (CameraActivity.mPowerShutter && !CameraUtil.hasCameraKey()
+ && mFirstTimeInitialized) {
+ onShutterButtonClick();
+ }
+ return true;
}
return false;
}
@@ -2971,6 +3061,8 @@ public class PhotoModule
return;
}
+ String focusMode;
+
synchronized (mCameraDevice) {
SurfaceHolder sh = null;
Log.v(TAG, "startPreview: SurfaceHolder (MDP path)");
@@ -2988,13 +3080,14 @@ public class PhotoModule
}
mErrorCallback.setActivity(mActivity);
mCameraDevice.setErrorCallback(mErrorCallback);
- // ICS camera frameworks has a bug. Face detection state is not cleared 1589
- // after taking a picture. Stop the preview to work around it. The bug
- // was fixed in JB.
+
+ // Reset camera state after taking a picture
if (mCameraState != PREVIEW_STOPPED && mCameraState != INIT) {
- stopPreview();
+ setCameraState(IDLE);
}
+ if (mFocusManager == null) initializeFocusManager();
+
if (!mSnapshotOnIdle) {
mFocusManager.setAeAwbLock(false); // Unlock AE and AWB.
}
@@ -3016,7 +3109,10 @@ public class PhotoModule
if (!mSnapshotOnIdle && !mInstantCaptureSnapShot) {
// If the focus mode is continuous autofocus, call cancelAutoFocus to
// resume it because it may have been paused by autoFocus call.
- if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusManager.getFocusMode()) && mCameraState !=INIT) {
+ focusMode = mFocusManager.getFocusMode(false);
+ if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(focusMode) &&
+ mCameraState != INIT ||
+ CameraUtil.FOCUS_MODE_MW_CONTINUOUS_PICTURE.equals(focusMode)) {
mCameraDevice.cancelAutoFocus();
}
} else {
@@ -3028,6 +3124,10 @@ public class PhotoModule
@Override
public void stopPreview() {
if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) {
+ if (mCameraState == LONGSHOT) {
+ mCameraDevice.setLongshot(false);
+ mLongshotActive = false;
+ }
Log.v(TAG, "stopPreview");
mCameraDevice.stopPreview();
}
@@ -3139,42 +3239,55 @@ public class PhotoModule
}
}
+ private String getSaturationSafe() {
+ String ret = null;
+ if (CameraUtil.isSupported(mParameters, "saturation") &&
+ CameraUtil.isSupported(mParameters, "max-saturation")) {
+ ret = mPreferences.getString(
+ CameraSettings.KEY_SATURATION,
+ mActivity.getString(R.string.pref_camera_saturation_default));
+ }
+ return ret;
+ }
+
+ private String getContrastSafe() {
+ String ret = null;
+ if (CameraUtil.isSupported(mParameters, "contrast") &&
+ CameraUtil.isSupported(mParameters, "max-contrast")) {
+ ret = mPreferences.getString(
+ CameraSettings.KEY_CONTRAST,
+ mActivity.getString(R.string.pref_camera_contrast_default));
+ }
+ return ret;
+ }
+
+ private String getSharpnessSafe() {
+ String ret = null;
+ if (CameraUtil.isSupported(mParameters, "sharpness") &&
+ CameraUtil.isSupported(mParameters, "max-sharpness")) {
+ ret = mPreferences.getString(
+ CameraSettings.KEY_SHARPNESS,
+ mActivity.getString(R.string.pref_camera_sharpness_default));
+ }
+ return ret;
+ }
+
/** This can run on a background thread, so don't do UI updates here.*/
private void qcomUpdateCameraParametersPreference() {
//qcom Related Parameter update
- //Set Brightness.
- mParameters.set("luma-adaptation", String.valueOf(mbrightness));
-
String longshot_enable = mPreferences.getString(
CameraSettings.KEY_LONGSHOT,
mActivity.getString(R.string.pref_camera_longshot_default));
mParameters.set("long-shot", longshot_enable);
String optizoomOn = mActivity.getString(R.string
.pref_camera_advanced_feature_value_optizoom_on);
+ String chromaFlashOn = mActivity.getString(R.string
+ .pref_camera_advanced_feature_value_chromaflash_on);
- if (Parameters.SCENE_MODE_AUTO.equals(mSceneMode) ||
- CameraUtil.SCENE_MODE_HDR.equals(mSceneMode) ||
- optizoomOn.equals(mSceneMode)) {
- // Set Touch AF/AEC parameter.
- String touchAfAec = mPreferences.getString(
- CameraSettings.KEY_TOUCH_AF_AEC,
- mActivity.getString(R.string.pref_camera_touchafaec_default));
- if (CameraUtil.isSupported(touchAfAec,
- ParametersWrapper.getSupportedTouchAfAec(mParameters))) {
- mCurrTouchAfAec = touchAfAec;
- ParametersWrapper.setTouchAfAec(mParameters, touchAfAec);
- }
- } else {
- ParametersWrapper.setTouchAfAec(mParameters, ParametersWrapper.TOUCH_AF_AEC_OFF);
- mFocusManager.resetTouchFocus();
- }
- try {
- if(ParametersWrapper.getTouchAfAec(mParameters).equals(ParametersWrapper.TOUCH_AF_AEC_ON))
- this.mTouchAfAecFlag = true;
- else
- this.mTouchAfAecFlag = false;
- } catch(Exception e){
- Log.e(TAG, "Handled NULL pointer Exception");
+ // Set Touch AF/AEC parameter.
+ if (CameraUtil.isSupported(mParameters.TOUCH_AF_AEC_ON,
+ mParameters.getSupportedTouchAfAec())) {
+ mParameters.setTouchAfAec(mParameters.TOUCH_AF_AEC_ON);
}
// Set Picture Format
@@ -3199,26 +3312,20 @@ public class PhotoModule
String jpegQuality = mPreferences.getString(
CameraSettings.KEY_JPEG_QUALITY,
mActivity.getString(R.string.pref_camera_jpegquality_default));
- //mUnsupportedJpegQuality = false;
Size pic_size = mParameters.getPictureSize();
if (pic_size == null) {
Log.e(TAG, "error getPictureSize: size is null");
- }
- else{
- if("100".equals(jpegQuality) && (pic_size.width >= 3200)){
- //mUnsupportedJpegQuality = true;
- }else {
- mParameters.setJpegQuality(JpegEncodingQualityMappings.getQualityNumber(jpegQuality));
- int jpegFileSize = estimateJpegFileSize(pic_size, jpegQuality);
- if (jpegFileSize != mJpegFileSizeEstimation) {
- mJpegFileSizeEstimation = jpegFileSize;
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- updateRemainingPhotos();
- }
- });
- }
+ } else {
+ mParameters.setJpegQuality(JpegEncodingQualityMappings.getQualityNumber(jpegQuality));
+ int jpegFileSize = estimateJpegFileSize(pic_size, jpegQuality);
+ if (jpegFileSize != mJpegFileSizeEstimation) {
+ mJpegFileSizeEstimation = jpegFileSize;
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ updateRemainingPhotos();
+ }
+ });
}
}
@@ -3252,10 +3359,18 @@ public class PhotoModule
CameraSettings.KEY_ISO,
mActivity.getString(R.string.pref_camera_iso_default));
if (CameraUtil.isSupported(iso,
- ParametersWrapper.getSupportedIsoValues(mParameters))) {
- ParametersWrapper.setISOValue(mParameters, iso);
+ CameraSettings.getSupportedIsoValues(mParameters))) {
+ CameraSettings.setISOValue(mParameters, iso);
}
}
+ // Set shutter speed parameter
+ String shutterSpeed = mPreferences.getString(
+ CameraSettings.KEY_SHUTTER_SPEED,
+ mActivity.getString(R.string.pref_camera_shutter_speed_default));
+ if (CameraUtil.isSupported(shutterSpeed,
+ CameraSettings.getSupportedShutterSpeedValues(mParameters))) {
+ mParameters.set(CameraSettings.KEY_SNAPCAM_SHUTTER_SPEED, shutterSpeed);
+ }
// Set color effect parameter.
String colorEffect = mPreferences.getString(
CameraSettings.KEY_COLOR_EFFECT,
@@ -3266,32 +3381,35 @@ public class PhotoModule
}
//Set Saturation
- String saturationStr = mPreferences.getString(
- CameraSettings.KEY_SATURATION,
- mActivity.getString(R.string.pref_camera_saturation_default));
- int saturation = Integer.parseInt(saturationStr);
- Log.v(TAG, "Saturation value =" + saturation);
- if((0 <= saturation) && (saturation <= ParametersWrapper.getMaxSaturation(mParameters))){
- ParametersWrapper.setSaturation(mParameters, saturation);
+ String saturationStr = getSaturationSafe();
+ if (saturationStr != null) {
+ int saturation = Integer.parseInt(saturationStr);
+ Log.v(TAG, "Saturation value =" + saturation);
+ if ((0 <= saturation) &&
+ (saturation <= ParametersWrapper.getMaxSaturation(mParameters))) {
+ ParametersWrapper.setSaturation(mParameters, saturation);
+ }
}
// Set contrast parameter.
- String contrastStr = mPreferences.getString(
- CameraSettings.KEY_CONTRAST,
- mActivity.getString(R.string.pref_camera_contrast_default));
- int contrast = Integer.parseInt(contrastStr);
- Log.v(TAG, "Contrast value =" +contrast);
- if((0 <= contrast) && (contrast <= ParametersWrapper.getMaxContrast(mParameters))){
- ParametersWrapper.setContrast(mParameters, contrast);
+ String contrastStr = getContrastSafe();
+ if (contrastStr != null) {
+ int contrast = Integer.parseInt(contrastStr);
+ Log.v(TAG, "Contrast value =" + contrast);
+ if ((0 <= contrast) &&
+ (contrast <= ParametersWrapper.getMaxContrast(mParameters))) {
+ ParametersWrapper.setContrast(mParameters, contrast);
+ }
}
// Set sharpness parameter
- String sharpnessStr = mPreferences.getString(
- CameraSettings.KEY_SHARPNESS,
- mActivity.getString(R.string.pref_camera_sharpness_default));
- int sharpness = Integer.parseInt(sharpnessStr) *
- (ParametersWrapper.getMaxSharpness(mParameters)/MAX_SHARPNESS_LEVEL);
- Log.v(TAG, "Sharpness value =" + sharpness);
- if((0 <= sharpness) && (sharpness <= ParametersWrapper.getMaxSharpness(mParameters))){
- ParametersWrapper.setSharpness(mParameters, sharpness);
+ String sharpnessStr = getSharpnessSafe();
+ if (sharpnessStr != null) {
+ int sharpness = Integer.parseInt(sharpnessStr) *
+ (ParametersWrapper.getMaxSharpness(mParameters)/MAX_SHARPNESS_LEVEL);
+ Log.v(TAG, "Sharpness value =" + sharpness);
+ if ((0 <= sharpness) &&
+ (sharpness <= ParametersWrapper.getMaxSharpness(mParameters))) {
+ ParametersWrapper.setSharpness(mParameters, sharpness);
+ }
}
// Set Face Recognition
String faceRC = mPreferences.getString(
@@ -3363,22 +3481,12 @@ public class PhotoModule
String hdrMode = mPreferences.getString(
CameraSettings.KEY_HDR_MODE,
mActivity.getString(R.string.pref_camera_hdr_mode_default));
- Log.v(TAG, "HDR Mode value =" + hdrMode);
if (CameraUtil.isSupported(hdrMode,
CameraSettings.getSupportedHDRModes(mParameters))) {
+ Log.v(TAG, "HDR Mode value =" + hdrMode);
mParameters.set(CameraSettings.KEY_SNAPCAM_HDR_MODE, hdrMode);
}
- // Set hdr need 1x
- String hdrNeed1x = mPreferences.getString(
- CameraSettings.KEY_HDR_NEED_1X,
- mActivity.getString(R.string.pref_camera_hdr_need_1x_default));
- Log.v(TAG, "HDR need 1x value =" + hdrNeed1x);
- if (CameraUtil.isSupported(hdrNeed1x,
- CameraSettings.getSupportedHDRNeed1x(mParameters))) {
- mParameters.set(CameraSettings.KEY_SNAPCAM_HDR_NEED_1X, hdrNeed1x);
- }
-
// Set Advanced features.
String advancedFeature = mPreferences.getString(
CameraSettings.KEY_ADVANCED_FEATURES,
@@ -3566,32 +3674,6 @@ public class PhotoModule
String zsl = mPreferences.getString(CameraSettings.KEY_ZSL,
mActivity.getString(R.string.pref_camera_zsl_default));
- String auto_hdr = mPreferences.getString(CameraSettings.KEY_AUTO_HDR,
- mActivity.getString(R.string.pref_camera_hdr_default));
- if (CameraUtil.isAutoHDRSupported(mParameters)) {
- mParameters.set("auto-hdr-enable",auto_hdr);
- if (auto_hdr.equals("enable")) {
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- if (mDrawAutoHDR != null) {
- mDrawAutoHDR.setVisibility(View.VISIBLE);
- }
- }
- });
- mParameters.setSceneMode("asd");
- mCameraDevice.setMetadataCb(mMetaDataCallback);
- }
- else {
- mAutoHdrEnable = false;
- mActivity.runOnUiThread( new Runnable() {
- public void run () {
- if (mDrawAutoHDR != null) {
- mDrawAutoHDR.setVisibility (View.INVISIBLE);
- }
- }
- });
- }
- }
ParametersWrapper.setZSLMode(mParameters, zsl);
if(zsl.equals("on") && ParametersWrapper.getSupportedZSLModes(mParameters) != null) {
//Switch on ZSL Camera mode
@@ -3603,16 +3685,22 @@ public class PhotoModule
mParameters.set(KEY_PICTURE_FORMAT, PIXEL_FORMAT_JPEG);
//Try to set CAF for ZSL
- if(CameraUtil.isSupported(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE,
- mParameters.getSupportedFocusModes()) && !mFocusManager.isTouch()) {
- mFocusManager.overrideFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
- mParameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
+ if (!mFocusManager.isTouch()) {
+ if (CameraUtil.isSupported(CameraUtil.FOCUS_MODE_MW_CONTINUOUS_PICTURE,
+ mParameters.getSupportedFocusModes())) {
+ mFocusManager.overrideFocusMode(CameraUtil.FOCUS_MODE_MW_CONTINUOUS_PICTURE);
+ mParameters.setFocusMode(CameraUtil.FOCUS_MODE_MW_CONTINUOUS_PICTURE);
+ } else if (CameraUtil.isSupported(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE,
+ mParameters.getSupportedFocusModes())) {
+ mFocusManager.overrideFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
+ mParameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
+ }
} else if (mFocusManager.isTouch()) {
mFocusManager.overrideFocusMode(null);
- mParameters.setFocusMode(mFocusManager.getFocusMode());
+ mParameters.setFocusMode(mFocusManager.getFocusMode(false));
} else {
// If not supported use the current mode
- mFocusManager.overrideFocusMode(mFocusManager.getFocusMode());
+ mFocusManager.overrideFocusMode(mFocusManager.getFocusMode(false));
}
if (!pictureFormat.equals(PIXEL_FORMAT_JPEG)) {
@@ -3629,7 +3717,7 @@ public class PhotoModule
mFocusManager.setZslEnable(false);
if ((mManual3AEnabled & MANUAL_FOCUS) == 0) {
mFocusManager.overrideFocusMode(null);
- mParameters.setFocusMode(mFocusManager.getFocusMode());
+ mParameters.setFocusMode(mFocusManager.getFocusMode(false));
}
}
@@ -3665,6 +3753,8 @@ public class PhotoModule
+ mInstantCaptureSnapShot);
mParameters.set(CameraSettings.KEY_QC_INSTANT_CAPTURE, instantCapture);
+ updateAutoHDR();
+
//Set Histogram
String histogram = mPreferences.getString(
CameraSettings.KEY_HISTOGRAM,
@@ -3704,9 +3794,9 @@ public class PhotoModule
mParameters.setFlashMode(fMode);
}
- if(!mFocusManager.getFocusMode().equals(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) &&
+ if(!mFocusManager.getFocusMode(false).equals(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) &&
!mFocusManager.isFocusCompleted()) {
- mUI.clearFocus();
+ mUI.getFocusRing().stopFocusAnimations();
}
String bokehMode = mPreferences.getString(
@@ -3772,6 +3862,9 @@ public class PhotoModule
mParameters.set(CameraSettings.KEY_QC_BOKEH_BLUR_VALUE, bokehBlurDegree);
Log.v(TAG, "Bokeh Mode = " + bokehMode + " bokehMpo = " + bokehMpo +
" bokehBlurDegree = " + bokehBlurDegree);
+
+ mLongShotMaxSnap = SystemProperties.getInt(PERSIST_LONGSHOT_MAX_SNAP, -1);
+ mParameters.set("max-longshot-snap",mLongShotMaxSnap);
}
private int estimateJpegFileSize(final Size size, final String quality) {
@@ -3793,6 +3886,44 @@ public class PhotoModule
}
}
+ private void updateAutoHDR() {
+ String autoHdr = mPreferences.getString(CameraSettings.KEY_AUTO_HDR,
+ mActivity.getString(R.string.pref_camera_auto_hdr_default));
+ String advancedFeature = mPreferences.getString(
+ CameraSettings.KEY_ADVANCED_FEATURES,
+ mActivity.getString(R.string.pref_camera_advanced_feature_default));
+
+ if (CameraUtil.isAutoHDRSupported(mParameters)) {
+ if (autoHdr.equals("enable") &&
+ ("asd".equals(mSceneMode) || "auto".equals(mSceneMode)) &&
+ CameraUtil.isSupported("asd", mParameters.getSupportedSceneModes()) &&
+ (advancedFeature == null || "none".equals(advancedFeature))) {
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ if (mDrawAutoHDR != null) {
+ mDrawAutoHDR.setVisibility(View.VISIBLE);
+ }
+ }
+ });
+ mParameters.setSceneMode("asd");
+ mCameraDevice.setMetadataCb(mMetaDataCallback);
+ mParameters.set("auto-hdr-enable", "enable");
+ }
+ else {
+ mAutoHdrEnable = false;
+ mActivity.runOnUiThread( new Runnable() {
+ public void run () {
+ if (mDrawAutoHDR != null) {
+ mDrawAutoHDR.setVisibility (View.INVISIBLE);
+ }
+ }
+ });
+ mCameraDevice.setMetadataCb(null);
+ mParameters.set("auto-hdr-enable", "disable");
+ }
+ }
+ }
+
private void setFlipValue() {
// Read Flip mode from adb command
//value: 0(default) - FLIP_MODE_OFF
@@ -3927,7 +4058,7 @@ public class PhotoModule
// initialize focus mode
if ((mManual3AEnabled & MANUAL_FOCUS) == 0) {
mFocusManager.overrideFocusMode(null);
- mParameters.setFocusMode(mFocusManager.getFocusMode());
+ mParameters.setFocusMode(mFocusManager.getFocusMode(false));
}
// Set picture size.
@@ -4039,8 +4170,8 @@ public class PhotoModule
mActivity.getString(R.string.pref_camera_hdr_plus_default));
boolean hdrOn = onValue.equals(hdr);
boolean hdrPlusOn = onValue.equals(hdrPlus);
-
boolean doGcamModeSwitch = false;
+
if (hdrPlusOn && GcamHelper.hasGcamCapture()) {
// Kick off mode switch to gcam.
doGcamModeSwitch = true;
@@ -4053,7 +4184,20 @@ public class PhotoModule
mCameraDevice.setParameters(mParameters);
mParameters = mCameraDevice.getParameters();
}
+ if (mLgeHdrMode) {
+ mParameters.set(CameraSettings.KEY_SNAPCAM_HDR_MODE,
+ CameraSettings.LGE_HDR_MODE_ON);
+ try {
+ // Force enable ZSL mode for LG HDR
+ mUI.setPreference(CameraSettings.KEY_ZSL, Parameters.ZSL_ON);
+ } catch (NullPointerException e) {
+ }
+ }
} else {
+ if (mLgeHdrMode) {
+ mParameters.set(CameraSettings.KEY_SNAPCAM_HDR_MODE,
+ CameraSettings.LGE_HDR_MODE_OFF);
+ }
mSceneMode = mPreferences.getString(
CameraSettings.KEY_SCENE_MODE,
mActivity.getString(R.string.pref_camera_scenemode_default));
@@ -4064,7 +4208,10 @@ public class PhotoModule
.pref_camera_advanced_feature_value_refocus_on);
String optizoomOn = mActivity.getString(R.string
.pref_camera_advanced_feature_value_optizoom_on);
+ String chromaFlashOn = mActivity.getString(R.string
+ .pref_camera_advanced_feature_value_chromaflash_on);
String scenModeStr = mSceneMode;
+
if (refocusOn.equals(mSceneMode)) {
try {
mSceneMode = Parameters.SCENE_MODE_AUTO;
@@ -4082,6 +4229,12 @@ public class PhotoModule
}
} catch (NullPointerException e) {
}
+ } else if (chromaFlashOn.equals(mSceneMode)) {
+ try {
+ mUI.setPreference(CameraSettings.KEY_ADVANCED_FEATURES, chromaFlashOn);
+ mParameters.setSceneMode(Parameters.SCENE_MODE_AUTO);
+ } catch (NullPointerException e) {
+ }
} else if (mSceneMode == null) {
mSceneMode = Parameters.SCENE_MODE_AUTO;
}
@@ -4112,6 +4265,19 @@ public class PhotoModule
mParameters.setJpegQuality(jpegQuality);
+ // When shutter speed gets disabled preview needs to be restarted
+ if (CameraUtil.isSupported(mParameters, CameraSettings.KEY_SNAPCAM_SHUTTER_SPEED)) {
+ String shutterSpeed = mPreferences.getString(CameraSettings.KEY_SHUTTER_SPEED, null);
+ if (shutterSpeed != null) {
+ String oldShutterSpeed = mParameters.get(CameraSettings.KEY_SNAPCAM_SHUTTER_SPEED);
+ if (!shutterSpeed.equals(oldShutterSpeed) && shutterSpeed.equals("0") &&
+ mCameraState != PREVIEW_STOPPED) {
+ Log.v(TAG, "Shutter speed disabled. Restart Preview");
+ mRestartPreview = true;
+ }
+ }
+ }
+
// For the following settings, we need to check if the settings are
// still supported by latest driver, if not, ignore the settings.
@@ -4125,7 +4291,8 @@ public class PhotoModule
Log.w(TAG, "invalid exposure range: " + value);
}
- if (Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) {
+ if (Parameters.SCENE_MODE_AUTO.equals(mSceneMode) ||
+ "asd".equals(mSceneMode) || "sports".equals(mSceneMode)) {
// Set flash mode.
String flashMode;
if (mSavedFlashMode == null) {
@@ -4170,13 +4337,19 @@ public class PhotoModule
mParameters.setFocusMode(Parameters.FOCUS_MODE_INFINITY);
} else if ((mManual3AEnabled & MANUAL_FOCUS) == 0) {
mFocusManager.overrideFocusMode(null);
- mParameters.setFocusMode(mFocusManager.getFocusMode());
+ mParameters.setFocusMode(mFocusManager.getFocusMode(false));
}
+
+ // Set focus time.
+ mFocusManager.setFocusTime(Integer.decode(
+ mPreferences.getString(CameraSettings.KEY_FOCUS_TIME,
+ mActivity.getString(R.string.pref_camera_focustime_default))));
} else {
mFocusManager.overrideFocusMode(mParameters.getFocusMode());
- if (CameraUtil.isSupported(Parameters.FLASH_MODE_OFF,
- mParameters.getSupportedFlashModes())) {
- mParameters.setFlashMode(Parameters.FLASH_MODE_OFF);
+ String flashMode = chromaFlashOn.equals(mSceneMode) ?
+ Parameters.FLASH_MODE_ON : Parameters.FLASH_MODE_OFF;
+ if (CameraUtil.isSupported(flashMode, mParameters.getSupportedFlashModes())) {
+ mParameters.setFlashMode(flashMode);
}
if (CameraUtil.isSupported(Parameters.WHITE_BALANCE_AUTO,
mParameters.getSupportedWhiteBalance())) {
@@ -4211,7 +4384,8 @@ public class PhotoModule
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void updateAutoFocusMoveCallback() {
- if (mParameters.getFocusMode().equals(CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE)) {
+ if (mParameters.getFocusMode().equals(CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE) ||
+ mParameters.getFocusMode().equals(CameraUtil.FOCUS_MODE_MW_CONTINUOUS_PICTURE)) {
mCameraDevice.setAutoFocusMoveCallback(mHandler,
(CameraAFMoveCallback) mAutoFocusMoveCallback);
} else {
@@ -4241,7 +4415,9 @@ public class PhotoModule
doModeSwitch = updateCameraParametersPreference();
}
+ CameraUtil.dumpParameters(mParameters);
mCameraDevice.setParameters(mParameters);
+ mFocusManager.setParameters(mParameters);
// Switch to gcam module if HDR+ was selected
if (doModeSwitch && !mIsImageCaptureIntent) {
@@ -4332,7 +4508,14 @@ public class PhotoModule
final int maxFocusPos = mParameters.getInt(CameraSettings.KEY_MAX_FOCUS_SCALE);
//update mparameters to fetch latest focus position
mParameters = mCameraDevice.getParameters();
- final int CurFocusPos = mParameters.getInt(CameraSettings.KEY_MANUAL_FOCUS_SCALE);
+ int CurFocusPos = minFocusPos;
+
+ try {
+ CurFocusPos = mParameters.getInt(CameraSettings.KEY_MANUAL_FOCUS_SCALE);
+ } catch (NumberFormatException e) {
+ // Do nothing
+ }
+
focusbar.setProgress(CurFocusPos);
focusPositionText.setText("Current focus position is " + CurFocusPos);
@@ -4384,7 +4567,8 @@ public class PhotoModule
//update mparameters to fetch latest focus position
mParameters = mCameraDevice.getParameters();
final String CurFocusPos = mParameters.get(CameraSettings.KEY_MANUAL_FOCUS_DIOPTER);
- focusPositionText.setText("Current focus position is " + CurFocusPos);
+ focusPositionText.setText("Current focus position is " +
+ (CurFocusPos != null ? CurFocusPos : minFocusStr));
linear.addView(input);
linear.addView(focusPositionText);
alert.setView(linear);
@@ -4425,7 +4609,7 @@ public class PhotoModule
alert.show();
} else {
mManual3AEnabled &= ~MANUAL_FOCUS;
- mParameters.setFocusMode(mFocusManager.getFocusMode());
+ mParameters.setFocusMode(mFocusManager.getFocusMode(false));
mUI.overrideSettings(CameraSettings.KEY_FOCUS_MODE, null);
updateCommonManual3ASettings();
onSharedPreferenceChanged();
@@ -4611,7 +4795,7 @@ public class PhotoModule
mParameters = mCameraDevice.getParameters();
final int minISO = mParameters.getInt(CameraSettings.KEY_MIN_ISO);
final int maxISO = mParameters.getInt(CameraSettings.KEY_MAX_ISO);
- String isoMode = ParametersWrapper.getISOValue(mParameters);
+ String isoMode = CameraSettings.getISOValue(mParameters);
final String isoManual = CameraSettings.KEY_MANUAL_ISO;
String currentISO = mParameters.get(CameraSettings.KEY_CURRENT_ISO);
if (currentISO != null) {
@@ -4653,7 +4837,7 @@ public class PhotoModule
if (newISO <= maxISO && newISO >= minISO) {
Log.v(TAG, "Setting ISO : " + newISO);
mManual3AEnabled |= MANUAL_EXPOSURE;
- ParametersWrapper.setISOValue(mParameters, isoManual);
+ CameraSettings.setISOValue(mParameters, isoManual);
mParameters.set(CameraSettings.KEY_CONTINUOUS_ISO, newISO);
mParameters.set(CameraSettings.KEY_EXPOSURE_TIME, "0");
updateCommonManual3ASettings();
@@ -4689,7 +4873,7 @@ public class PhotoModule
Log.v(TAG, "Setting Exposure time : " + newExpTime);
mManual3AEnabled |= MANUAL_EXPOSURE;
mParameters.set(CameraSettings.KEY_EXPOSURE_TIME, expTime);
- ParametersWrapper.setISOValue(mParameters, ParametersWrapper.ISO_AUTO);
+ CameraSettings.setISOValue(mParameters, Parameters.ISO_AUTO);
mUI.setPreference(CameraSettings.KEY_ISO, ParametersWrapper.ISO_AUTO);
mUI.overrideSettings(CameraSettings.KEY_ISO, null);
updateCommonManual3ASettings();
@@ -4741,7 +4925,7 @@ public class PhotoModule
newExpTime >= Double.parseDouble(minExpTime)) {
mManual3AEnabled |= MANUAL_EXPOSURE;
Log.v(TAG, "Setting ISO : " + newISO);
- ParametersWrapper.setISOValue(mParameters, isoManual);
+ CameraSettings.setISOValue(mParameters, isoManual);
mParameters.set(CameraSettings.KEY_CONTINUOUS_ISO, newISO);
Log.v(TAG, "Setting Exposure time : " + newExpTime);
mParameters.set(CameraSettings.KEY_EXPOSURE_TIME, expTime);
@@ -4776,6 +4960,8 @@ public class PhotoModule
//filter off unsupported settings
final String settingOff = mActivity.getString(R.string.setting_off_value);
+ final String settingOn = mActivity.getString(R.string.setting_on_value);
+ final String zsl = mActivity.getString(R.string.pref_camera_zsl_default);
if (!CameraSettings.isZSLHDRSupported(mParameters)) {
//HDR internally uses AE-bracketing. Disable both if not supported.
if (notSame(pref, CameraSettings.KEY_CAMERA_HDR, settingOff) ||
@@ -4784,6 +4970,9 @@ public class PhotoModule
} else if (notSame(pref,CameraSettings.KEY_ZSL,settingOff)) {
mUI.setPreference(CameraSettings.KEY_CAMERA_HDR, settingOff);
mUI.setPreference(CameraSettings.KEY_AE_BRACKET_HDR, settingOff);
+ } else if (notSame(pref, CameraSettings.KEY_CAMERA_HDR, settingOn) ||
+ notSame(pref, CameraSettings.KEY_AE_BRACKET_HDR, settingOn)) {
+ mUI.setPreference(CameraSettings.KEY_ZSL, zsl);
}
}
@@ -4807,7 +4996,8 @@ public class PhotoModule
updateRemainingPhotos();
}
- if (CameraSettings.KEY_QC_CHROMA_FLASH.equals(pref.getKey())) {
+ if (!CameraSettings.hasChromaFlashScene(mActivity) &&
+ CameraSettings.KEY_QC_CHROMA_FLASH.equals(pref.getKey())) {
mUI.setPreference(CameraSettings.KEY_ADVANCED_FEATURES, pref.getValue());
}
@@ -4820,35 +5010,6 @@ public class PhotoModule
mUI.setPreference(CameraSettings.KEY_ADVANCED_FEATURES, pref.getValue());
}
- String ubiFocusOff = mActivity.getString(R.string.
- pref_camera_advanced_feature_value_ubifocus_off);
- String chromaFlashOff = mActivity.getString(R.string.
- pref_camera_advanced_feature_value_chromaflash_off);
- String optiZoomOff = mActivity.getString(R.string.
- pref_camera_advanced_feature_value_optizoom_off);
- String reFocusOff = mActivity.getString(R.string.
- pref_camera_advanced_feature_value_refocus_off);
- String fssrOff = mActivity.getString(R.string.
- pref_camera_advanced_feature_value_FSSR_off);
- String truePortraitOff = mActivity.getString(R.string.
- pref_camera_advanced_feature_value_trueportrait_off);
- String multiTouchFocusOff = mActivity.getString(R.string.
- pref_camera_advanced_feature_value_multi_touch_focus_off);
- String stillMoreOff = mActivity.getString(R.string.
- pref_camera_advanced_feature_value_stillmore_off);
- String advancedFeatureOff = mActivity.getString(R.string.
- pref_camera_advanced_feature_value_none);
- if (notSame(pref, CameraSettings.KEY_QC_OPTI_ZOOM, optiZoomOff) ||
- notSame(pref, CameraSettings.KEY_QC_AF_BRACKETING, ubiFocusOff) ||
- notSame(pref, CameraSettings.KEY_QC_FSSR, fssrOff) ||
- notSame(pref, CameraSettings.KEY_QC_TP, truePortraitOff) ||
- notSame(pref, CameraSettings.KEY_QC_MULTI_TOUCH_FOCUS, multiTouchFocusOff) ||
- notSame(pref, CameraSettings.KEY_QC_STILL_MORE, stillMoreOff) ||
- notSame(pref, CameraSettings.KEY_QC_RE_FOCUS, reFocusOff) ||
- notSame(pref, CameraSettings.KEY_ADVANCED_FEATURES, advancedFeatureOff)) {
- RotateTextToast.makeText(mActivity, R.string.advanced_capture_disable_continuous_shot,
- Toast.LENGTH_LONG).show();
- }
//call generic onSharedPreferenceChanged
onSharedPreferenceChanged();
}
@@ -4863,6 +5024,7 @@ public class PhotoModule
mLocationManager.recordLocation(recordLocation);
if(needRestart()){
Log.v(TAG, "Restarting Preview... Camera Mode Changed");
+ setCameraParameters(UPDATE_PARAM_PREFERENCE);
stopPreview();
startPreview();
setCameraState(IDLE);
@@ -4875,8 +5037,8 @@ public class PhotoModule
* later by posting a message to the handler */
if (mUI.mMenuInitialized) {
setCameraParametersWhenIdle(UPDATE_PARAM_PREFERENCE);
- mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup,
- mPreferences);
+ mActivity.initPowerShutter(mPreferences);
+ mActivity.initMaxBrightness(mPreferences);
} else {
mHandler.sendEmptyMessage(SET_PHOTO_UI_PARAMS);
}
@@ -4943,8 +5105,15 @@ public class PhotoModule
mMeteringAreaSupported = CameraUtil.isMeteringAreaSupported(mInitialParams);
mAeLockSupported = CameraUtil.isAutoExposureLockSupported(mInitialParams);
mAwbLockSupported = CameraUtil.isAutoWhiteBalanceLockSupported(mInitialParams);
- mContinuousFocusSupported = mInitialParams.getSupportedFocusModes().contains(
- CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE);
+
+ List<String> supportedFocusModes = mInitialParams.getSupportedFocusModes();
+ if (supportedFocusModes != null &&
+ (supportedFocusModes.contains(CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE) ||
+ supportedFocusModes.contains(CameraUtil.FOCUS_MODE_MW_CONTINUOUS_PICTURE))) {
+ mContinuousFocusSupported = true;
+ } else {
+ mContinuousFocusSupported = false;
+ }
}
@Override
@@ -5159,6 +5328,10 @@ public class PhotoModule
enableRecordingLocation(false);
}
+ public boolean isLongshotDone() {
+ return ((mCameraState == LONGSHOT) && (mLongshotSnapNum == mReceivedSnapNum) &&
+ !mLongshotActive);
+ }
}
/* Below is no longer needed, except to get rid of compile error
@@ -5209,7 +5382,6 @@ class GraphView extends View {
private CameraManager.CameraProxy mGraphCameraDevice;
private float scaled;
private static final int STATS_SIZE = 256;
- private static final String TAG = "GraphView";
public GraphView(Context context, AttributeSet attrs) {
@@ -5229,9 +5401,7 @@ class GraphView extends View {
}
@Override
protected void onDraw(Canvas canvas) {
- Log.v(TAG, "in Camera.java ondraw");
- if(mPhotoModule == null || !mPhotoModule.mHiston ) {
- Log.e(TAG, "returning as histogram is off ");
+ if (mPhotoModule == null || !mPhotoModule.mHiston) {
return;
}
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index 50b5f64fe..806a68bad 100755
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -58,7 +58,6 @@ import android.widget.PopupWindow;
import android.widget.Toast;
import com.android.camera.CameraPreference.OnPreferenceChangedListener;
-import com.android.camera.FocusOverlayManager.FocusUI;
import com.android.camera.TsMakeupManager.MakeupLevelListener;
import com.android.camera.ui.AbstractSettingPopup;
import com.android.camera.ui.CameraControls;
@@ -66,10 +65,8 @@ import com.android.camera.ui.CameraRootView;
import com.android.camera.ui.CountDownView;
import com.android.camera.ui.CountDownView.OnCountDownFinishedListener;
import com.android.camera.ui.FaceView;
-import com.android.camera.ui.FocusIndicator;
import com.android.camera.ui.ListSubMenu;
import com.android.camera.ui.ModuleSwitcher;
-import com.android.camera.ui.MenuHelp;
import com.android.camera.ui.PieRenderer;
import com.android.camera.ui.PieRenderer.PieListener;
import com.android.camera.ui.RenderOverlay;
@@ -78,11 +75,11 @@ import com.android.camera.ui.RotateLayout;
import com.android.camera.ui.RotateTextToast;
import com.android.camera.ui.SelfieFlashView;
import com.android.camera.ui.ZoomRenderer;
+import com.android.camera.ui.focus.FocusRing;
import com.android.camera.util.CameraUtil;
public class PhotoUI implements PieListener,
PreviewGestures.SingleTapListener,
- FocusUI,
SurfaceHolder.Callback,
CameraRootView.MyDisplayListener,
CameraManager.CameraFaceDetectionCallback {
@@ -90,6 +87,7 @@ public class PhotoUI implements PieListener,
private static final String TAG = "CAM_UI";
private int mDownSampleFactor = 4;
private final AnimationManager mAnimationManager;
+ private final FocusRing mFocusRing;
private CameraActivity mActivity;
private PhotoController mController;
private PreviewGestures mGestures;
@@ -114,12 +112,8 @@ public class PhotoUI implements PieListener,
private PhotoMenu mMenu;
private ModuleSwitcher mSwitcher;
private CameraControls mCameraControls;
- private MenuHelp mMenuHelp;
private AlertDialog mLocationDialog;
- // Small indicators which show the camera settings in the viewfinder.
- private OnScreenIndicators mOnScreenIndicators;
-
private PieRenderer mPieRenderer;
private ZoomRenderer mZoomRenderer;
private RotateTextToast mNotSelectableToast;
@@ -296,17 +290,16 @@ public class PhotoUI implements PieListener,
mFaceView = (FaceView) mRootView.findViewById(R.id.face_view);
setSurfaceTextureSizeChangedListener(mFaceView);
}
- initIndicators();
+ mFocusRing = (FocusRing) mRootView.findViewById(R.id.focus_ring);
mAnimationManager = new AnimationManager();
mOrientationResize = false;
mPrevOrientationResize = false;
Point size = new Point();
- mActivity.getWindowManager().getDefaultDisplay().getSize(size);
+ mActivity.getWindowManager().getDefaultDisplay().getRealSize(size);
mScreenRatio = CameraUtil.determineRatio(size.x, size.y);
calculateMargins(size);
mCameraControls.setMargins(mTopMargin, mBottomMargin);
- showFirstTimeHelp();
}
private void calculateMargins(Point size) {
@@ -326,27 +319,10 @@ public class PhotoUI implements PieListener,
mOrientationResize = orientation;
}
- private void showFirstTimeHelp(int topMargin, int bottomMargin) {
- mMenuHelp = (MenuHelp) mRootView.findViewById(R.id.menu_help);
- mMenuHelp.setVisibility(View.VISIBLE);
- mMenuHelp.setMargins(topMargin, bottomMargin);
- mMenuHelp.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mMenuHelp != null) {
- mMenuHelp.setVisibility(View.GONE);
- mMenuHelp = null;
- }
- }
- });
- }
-
public void setAspectRatio(float ratio) {
if (ratio <= 0.0) throw new IllegalArgumentException();
- if (mOrientationResize &&
- mActivity.getResources().getConfiguration().orientation
- != Configuration.ORIENTATION_PORTRAIT) {
+ if (mOrientationResize && CameraUtil.isScreenRotated(mActivity)) {
ratio = 1 / ratio;
}
@@ -363,6 +339,9 @@ public class PhotoUI implements PieListener,
FrameLayout.LayoutParams lp;
float scaledTextureWidth, scaledTextureHeight;
int rotation = CameraUtil.getDisplayRotation(mActivity);
+ if (!CameraUtil.isDefaultToPortrait(mActivity)) {
+ rotation = (rotation - 90) % 360;
+ }
mScreenRatio = CameraUtil.determineRatio(ratio);
if (mScreenRatio == CameraUtil.RATIO_16_9
&& CameraUtil.determinCloseRatio(ratio) == CameraUtil.RATIO_4_3) {
@@ -397,8 +376,13 @@ public class PhotoUI implements PieListener,
} else {
float width = mMaxPreviewWidth, height = mMaxPreviewHeight;
if (width == 0 || height == 0) return;
- if(mScreenRatio == CameraUtil.RATIO_4_3)
- height -= (mTopMargin + mBottomMargin);
+ if (mScreenRatio == CameraUtil.RATIO_4_3) {
+ if (height > width) {
+ height -= (mTopMargin + mBottomMargin);
+ } else {
+ width -= (mTopMargin + mBottomMargin);
+ }
+ }
if (mOrientationResize) {
scaledTextureWidth = height * mAspectRatio;
if (scaledTextureWidth > width) {
@@ -497,11 +481,6 @@ public class PhotoUI implements PieListener,
return mRootView;
}
- private void initIndicators() {
- mOnScreenIndicators = new OnScreenIndicators(mActivity,
- mRootView.findViewById(R.id.on_screen_indicators));
- }
-
public void onCameraOpened(PreferenceGroup prefGroup, ComboPreferences prefs,
Camera.Parameters params, OnPreferenceChangedListener listener, MakeupLevelListener makeupListener) {
if (mPieRenderer == null) {
@@ -534,7 +513,6 @@ public class PhotoUI implements PieListener,
mRenderOverlay.requestLayout();
initializeZoom(params);
- updateOnScreenIndicators(params, prefGroup, prefs);
mActivity.setPreviewGestures(mGestures);
}
@@ -565,8 +543,9 @@ public class PhotoUI implements PieListener,
@Override
public void onClick(View v) {
if (!CameraControls.isAnimating()
- && mController.getCameraState() != PhotoController.SNAPSHOT_IN_PROGRESS)
+ && mController.getCameraState() != PhotoController.SNAPSHOT_IN_PROGRESS) {
mActivity.gotoGallery();
+ }
}
});
}
@@ -652,29 +631,11 @@ public class PhotoUI implements PieListener,
// called from onResume but only the first time
public void initializeFirstTime() {
// Initialize shutter button.
- mShutterButton.setImageResource(R.drawable.shutter_button_anim);
- mShutterButton.setOnClickListener(new OnClickListener()
- {
- @Override
- public void onClick(View v) {
- if (!CameraControls.isAnimating())
- doShutterAnimation();
- if (mController.isImageCaptureIntent()) {
- mCameraControls.setTitleBarVisibility(View.VISIBLE);
- }
- }
- });
-
+ mShutterButton.setImageResource(R.drawable.btn_new_shutter);
mShutterButton.setOnShutterButtonListener(mController);
mShutterButton.setVisibility(View.VISIBLE);
}
- public void doShutterAnimation() {
- AnimationDrawable frameAnimation = (AnimationDrawable) mShutterButton.getDrawable();
- frameAnimation.stop();
- frameAnimation.start();
- }
-
// called from onResume every other time
public void initializeSecondTime(Camera.Parameters params) {
initializeZoom(params);
@@ -709,29 +670,6 @@ public class PhotoUI implements PieListener,
mMenu.overrideSettings(keyvalues);
}
- public void updateOnScreenIndicators(Camera.Parameters params,
- PreferenceGroup group, ComboPreferences prefs) {
- if (params == null || group == null) return;
- mOnScreenIndicators.updateSceneOnScreenIndicator(params.getSceneMode());
- mOnScreenIndicators.updateExposureOnScreenIndicator(params,
- CameraSettings.readExposure(prefs));
- mOnScreenIndicators.updateFlashOnScreenIndicator(params.getFlashMode());
- int wbIndex = -1;
- String wb = Camera.Parameters.WHITE_BALANCE_AUTO;
- if (Camera.Parameters.SCENE_MODE_AUTO.equals(params.getSceneMode())) {
- wb = params.getWhiteBalance();
- }
- ListPreference pref = group.findPreference(CameraSettings.KEY_WHITE_BALANCE);
- if (pref != null) {
- wbIndex = pref.findIndexOfValue(wb);
- }
- // make sure the correct value was found
- // otherwise use auto index
- mOnScreenIndicators.updateWBIndicator(wbIndex < 0 ? 2 : wbIndex);
- boolean location = RecordLocationPreference.get(prefs, CameraSettings.KEY_RECORD_LOCATION);
- mOnScreenIndicators.updateLocationIndicator(location);
- }
-
public void setCameraState(int state) {
}
@@ -796,7 +734,6 @@ public class PhotoUI implements PieListener,
if (mPieRenderer != null) {
mPieRenderer.setBlockFocus(!previewFocused);
}
- setShowMenu(previewFocused);
if (!previewFocused && mCountDownView != null) mCountDownView.cancelCountDown();
}
@@ -876,8 +813,9 @@ public class PhotoUI implements PieListener,
mMenu.animateSlideIn(mMenuLayout, CameraActivity.SETTING_LIST_WIDTH_1, true);
if (level == 2)
mMenu.animateFadeIn(popup);
- } else
- popup.setAlpha(0.85f);
+ } else {
+ popup.setAlpha(1f);
+ }
}
public void removeLevel2() {
@@ -983,12 +921,6 @@ public class PhotoUI implements PieListener,
}
}
- private void setShowMenu(boolean show) {
- if (mOnScreenIndicators != null) {
- mOnScreenIndicators.setVisibility(show ? View.VISIBLE : View.GONE);
- }
- }
-
public boolean collapseCameraControls() {
// TODO: Mode switcher should behave like a popup and should hide itself when there
// is a touch outside of it.
@@ -1011,14 +943,12 @@ public class PhotoUI implements PieListener,
mCameraControls.hideCameraSettings();
mDecodeTaskForReview = new DecodeImageForReview(jpegData, orientation, mirror);
mDecodeTaskForReview.execute();
- mOnScreenIndicators.setVisibility(View.GONE);
mMenuButton.setVisibility(View.GONE);
CameraUtil.fadeIn(mReviewDoneButton);
mShutterButton.setVisibility(View.INVISIBLE);
CameraUtil.fadeIn(mReviewRetakeButton);
setOrientation(mOrientation, true);
mMenu.hideTopMenu(true);
- pauseFaceDetection();
}
protected void hidePostCaptureAlert() {
@@ -1027,7 +957,6 @@ public class PhotoUI implements PieListener,
mDecodeTaskForReview.cancel(true);
}
mReviewImage.setVisibility(View.GONE);
- mOnScreenIndicators.setVisibility(View.VISIBLE);
mMenuButton.setVisibility(View.VISIBLE);
if (mMenu != null) {
mMenu.hideTopMenu(false);
@@ -1035,7 +964,6 @@ public class PhotoUI implements PieListener,
CameraUtil.fadeOut(mReviewDoneButton);
mShutterButton.setVisibility(View.VISIBLE);
CameraUtil.fadeOut(mReviewRetakeButton);
- resumeFaceDetection();
}
public void setDisplayOrientation(int orientation) {
@@ -1242,61 +1170,8 @@ public class PhotoUI implements PieListener,
((CameraRootView) mRootView).removeDisplayChangeListener();
}
- // focus UI implementation
-
- private FocusIndicator getFocusIndicator() {
- return (mFaceView != null && mFaceView.faceExists()) ? mFaceView : mPieRenderer;
- }
-
- @Override
- public boolean hasFaces() {
- return (mFaceView != null && mFaceView.faceExists());
- }
-
- public void clearFaces() {
- if (mFaceView != null) mFaceView.clear();
- }
-
- @Override
- public void clearFocus() {
- FocusIndicator indicator = mPieRenderer;
- if (hasFaces()) {
- mFaceView.showStart();
- }
- if (indicator != null) indicator.clear();
- }
-
- @Override
- public void setFocusPosition(int x, int y) {
- mPieRenderer.setFocus(x, y);
- }
-
- @Override
- public void onFocusStarted() {
- FocusIndicator indicator = getFocusIndicator();
- if (indicator != null) indicator.showStart();
- }
-
- @Override
- public void onFocusSucceeded(boolean timeout) {
- FocusIndicator indicator = getFocusIndicator();
- if (indicator != null) indicator.showSuccess(timeout);
- }
-
- @Override
- public void onFocusFailed(boolean timeout) {
- FocusIndicator indicator = getFocusIndicator();
- if (indicator != null) indicator.showFail(timeout);
- }
-
- @Override
- public void pauseFaceDetection() {
- if (mFaceView != null) mFaceView.pause();
- }
-
- @Override
- public void resumeFaceDetection() {
- if (mFaceView != null) mFaceView.resume();
+ public FocusRing getFocusRing() {
+ return mFocusRing;
}
public void onStartFaceDetection(int orientation, boolean mirror) {
@@ -1320,6 +1195,13 @@ public class PhotoUI implements PieListener,
mFaceView.setFaces(faces);
}
+ public boolean onScaleStepResize(boolean direction) {
+ if (mGestures != null) {
+ return mGestures.onScaleStepResize(direction);
+ }
+ return false;
+ }
+
@Override
public void onDisplayChanged() {
Log.d(TAG, "Device flip detected.");
@@ -1338,8 +1220,6 @@ public class PhotoUI implements PieListener,
public void setOrientation(int orientation, boolean animation) {
mOrientation = orientation;
mCameraControls.setOrientation(orientation, animation);
- if (mMenuHelp != null)
- mMenuHelp.setOrientation(orientation, animation);
if (mMenuLayout != null)
mMenuLayout.setOrientation(orientation, animation);
if (mSubMenuLayout != null)
@@ -1389,6 +1269,7 @@ public class PhotoUI implements PieListener,
RotateImageView v = (RotateImageView) mReviewImage;
v.setOrientation(orientation, animation);
}
+ mOrientation = orientation;
}
public void tryToCloseSubList() {
@@ -1404,17 +1285,6 @@ public class PhotoUI implements PieListener,
setOrientation(mOrientation, true);
}
- public void showFirstTimeHelp() {
- final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mActivity);
- boolean isMenuShown = prefs.getBoolean(CameraSettings.KEY_SHOW_MENU_HELP, false);
- if(!isMenuShown) {
- showFirstTimeHelp(mTopMargin, mBottomMargin);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putBoolean(CameraSettings.KEY_SHOW_MENU_HELP, true);
- editor.apply();
- }
- }
-
public void showRefocusDialog() {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mActivity);
int prompt = prefs.getInt(CameraSettings.KEY_REFOCUS_PROMPT, 1);
diff --git a/src/com/android/camera/PreviewGestures.java b/src/com/android/camera/PreviewGestures.java
index 170476e82..4f01fba1b 100644
--- a/src/com/android/camera/PreviewGestures.java
+++ b/src/com/android/camera/PreviewGestures.java
@@ -88,17 +88,24 @@ public class PreviewGestures
return false;
}
if (mZoomOnly || mMode == MODE_ZOOM) return false;
-
int deltaX = (int) (e1.getX() - e2.getX());
int deltaY = (int) (e1.getY() - e2.getY());
int orientation = 0;
- if (mCaptureUI != null)
+ if (mPhotoMenu != null)
+ orientation = mPhotoMenu.getOrientation();
+ else if (mVideoMenu != null)
+ orientation = mVideoMenu.getOrientation();
+ else if (mCaptureUI != null)
orientation = mCaptureUI.getOrientation();
if (isLeftSwipe(orientation, deltaX, deltaY)) {
waitUntilNextDown = true;
- if (mCaptureUI != null)
+ if (mPhotoMenu != null && !mPhotoMenu.isMenuBeingShown())
+ mPhotoMenu.openFirstLevel();
+ else if (mVideoMenu != null && !mVideoMenu.isMenuBeingShown())
+ mVideoMenu.openFirstLevel();
+ else if (mCaptureUI != null)
mCaptureUI.openSettingsMenu();
return true;
}
@@ -264,10 +271,6 @@ public class PreviewGestures
return true;
}
- public boolean waitUntilNextDown() {
- return waitUntilNextDown;
- }
-
private MotionEvent makeCancelEvent(MotionEvent m) {
MotionEvent c = MotionEvent.obtain(m);
c.setAction(MotionEvent.ACTION_CANCEL);
@@ -309,5 +312,12 @@ public class PreviewGestures
public void onScaleEnd(ScaleGestureDetector detector) {
mZoom.onScaleEnd(detector);
}
+
+ public boolean onScaleStepResize(boolean direction) {
+ if (mZoom != null) {
+ return mZoom.onScaleStepResize(direction);
+ }
+ return false;
+ }
}
diff --git a/src/com/android/camera/SceneModeActivity.java b/src/com/android/camera/SceneModeActivity.java
index 9e0e59506..b32a55eb0 100644
--- a/src/com/android/camera/SceneModeActivity.java
+++ b/src/com/android/camera/SceneModeActivity.java
@@ -222,7 +222,6 @@ class MyPagerAdapter extends PagerAdapter {
v.setBackground(null);
}
}
- view.setBackgroundResource(R.drawable.scene_mode_view_border_selected);
SettingsManager.getInstance().setValueIndex(SettingsManager.KEY_SCENE_MODE, index);
mActivity.finish();
}
@@ -293,9 +292,6 @@ class GridAdapter extends BaseAdapter {
int idx = position + mPage * mActivity.getElmentPerPage();
viewHolder.imageView.setImageResource(mActivity.getThumbnails()[idx]);
viewHolder.textTitle.setText(mActivity.getEntries()[position + mPage * mActivity.getElmentPerPage()]);
- if (idx == mActivity.getCurrentScene()) {
- view.setBackgroundResource(R.drawable.scene_mode_view_border_selected);
- }
return view;
}
diff --git a/src/com/android/camera/SettingsManager.java b/src/com/android/camera/SettingsManager.java
index b62573b76..dd798bc68 100755
--- a/src/com/android/camera/SettingsManager.java
+++ b/src/com/android/camera/SettingsManager.java
@@ -328,14 +328,11 @@ public class SettingsManager implements ListMenu.SettingsListener {
}
public void updateQcfaPictureSize() {
- ListPreference picturePref = mPreferenceGroup.findPreference(KEY_PICTURE_SIZE);
- if (picturePref != null) {
- picturePref.setEntries(mContext.getResources().getStringArray(
- R.array.pref_camera2_picturesize_entries));
- picturePref.setEntryValues(mContext.getResources().getStringArray(
- R.array.pref_camera2_picturesize_entryvalues));
- filterUnsupportedOptions(picturePref, getSupportedPictureSize(
- getCurrentCameraId()));
+ ListPreference pictureSize = mPreferenceGroup.findPreference(KEY_PICTURE_SIZE);
+ if (pictureSize != null) {
+ CameraSettings.formatPictureSizes(pictureSize,
+ getSupportedPictureSizeList(getCurrentCameraId()), mContext);
+ CameraSettings.resetIfInvalid(pictureSize);
}
}
@@ -808,13 +805,9 @@ public class SettingsManager implements ListMenu.SettingsListener {
if (cameraIdPref != null) buildCameraId();
if (pictureSize != null) {
- if (filterUnsupportedOptions(pictureSize, getSupportedPictureSize(cameraId))) {
- mFilteredKeys.add(pictureSize.getKey());
- } else {
- if (filterSimilarPictureSize(mPreferenceGroup, pictureSize)) {
- mFilteredKeys.add(pictureSize.getKey());
- }
- }
+ CameraSettings.formatPictureSizes(pictureSize,
+ getSupportedPictureSizeList(cameraId), mContext);
+ CameraSettings.resetIfInvalid(pictureSize);
}
if (exposure != null) buildExposureCompensation(cameraId);
@@ -1308,6 +1301,43 @@ public class SettingsManager implements ListMenu.SettingsListener {
mValuesMap.get(KEY_FLASH_MODE) != null;
}
+ public boolean isZslSupported(int id) {
+ boolean zslSupported = false;
+ int [] capabilities = mCharacteristics.get(id)
+ .get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+ for (int capability : capabilities) {
+ if (capability == CameraCharacteristics
+ .REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING ||
+ capability == CameraCharacteristics
+ .REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING) {
+ zslSupported = true;
+ }
+ }
+ Log.d(TAG, "isZslSupported=" + zslSupported);
+ return zslSupported;
+ }
+
+ private List<Size> getSupportedPictureSizeList(int cameraId) {
+ StreamConfigurationMap map = mCharacteristics.get(cameraId).get(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ Size[] sizes = map.getOutputSizes(ImageFormat.JPEG);
+ List<Size> res = new ArrayList<>();
+ if (sizes != null) {
+ for (int i = 0; i < sizes.length; i++) {
+ res.add(sizes[i]);
+ }
+ }
+
+ Size[] highResSizes = map.getHighResolutionOutputSizes(ImageFormat.JPEG);
+ if (highResSizes != null) {
+ for (int i = 0; i < highResSizes.length; i++) {
+ res.add(highResSizes[i]);
+ }
+ }
+
+ return res;
+ }
+
private List<String> getSupportedPictureSize(int cameraId) {
StreamConfigurationMap map = mCharacteristics.get(cameraId).get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
diff --git a/src/com/android/camera/ShutterButton.java b/src/com/android/camera/ShutterButton.java
index b35658070..22223510c 100644
--- a/src/com/android/camera/ShutterButton.java
+++ b/src/com/android/camera/ShutterButton.java
@@ -22,14 +22,12 @@ import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
-import com.android.camera.ui.RotateImageView;
-
/**
* A button designed to be used for the on-screen shutter button.
* It's currently an {@code ImageView} that can call a delegate when the
* pressed state changes.
*/
-public class ShutterButton extends RotateImageView {
+public class ShutterButton extends ImageView {
private class LongClickListener implements View.OnLongClickListener {
public boolean onLongClick(View v) {
@@ -84,51 +82,6 @@ public class ShutterButton extends RotateImageView {
setLongClickable(enable);
}
- /**
- * Hook into the drawable state changing to get changes to isPressed -- the
- * onPressed listener doesn't always get called when the pressed state
- * changes.
- */
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
- final boolean pressed = isPressed();
- if (pressed != mOldPressed) {
- if (!pressed) {
- // When pressing the physical camera button the sequence of
- // events is:
- // focus pressed, optional camera pressed, focus released.
- // We want to emulate this sequence of events with the shutter
- // button. When clicking using a trackball button, the view
- // system changes the drawable state before posting click
- // notification, so the sequence of events is:
- // pressed(true), optional click, pressed(false)
- // When clicking using touch events, the view system changes the
- // drawable state after posting click notification, so the
- // sequence of events is:
- // pressed(true), pressed(false), optional click
- // Since we're emulating the physical camera button, we want to
- // have the same order of events. So we want the optional click
- // callback to be delivered before the pressed(false) callback.
- //
- // To do this, we delay the posting of the pressed(false) event
- // slightly by pushing it on the event queue. This moves it
- // after the optional click notification, so our client always
- // sees events in this sequence:
- // pressed(true), optional click, pressed(false)
- post(new Runnable() {
- @Override
- public void run() {
- callShutterButtonFocus(pressed);
- }
- });
- } else {
- callShutterButtonFocus(pressed);
- }
- mOldPressed = pressed;
- }
- }
-
private void callShutterButtonFocus(boolean pressed) {
if (mListener != null) {
mListener.onShutterButtonFocus(pressed);
diff --git a/src/com/android/camera/SoundPlayer.java b/src/com/android/camera/SoundPlayer.java
new file mode 100644
index 000000000..ff3f37f7a
--- /dev/null
+++ b/src/com/android/camera/SoundPlayer.java
@@ -0,0 +1,95 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.SoundPool;
+import android.util.SparseIntArray;
+
+import com.android.camera.util.ApiHelper;
+
+/**
+ * Loads a plays custom sounds. For playing system-standard sounds for various
+ * camera actions, please refer to {@link SoundClips}.
+ */
+public class SoundPlayer {
+ private final Context mAppContext;
+ private final SoundPool mSoundPool;
+ /** Keeps a mapping from sound resource ID to sound ID */
+ private final SparseIntArray mResourceToSoundId = new SparseIntArray();
+ private boolean mIsReleased = false;
+
+ /**
+ * Construct a new sound player.
+ */
+ public SoundPlayer(Context appContext) {
+ mAppContext = appContext;
+ final int audioType = getAudioTypeForSoundPool();
+ mSoundPool = new SoundPool(1 /* max streams */, audioType, 0 /* quality */);
+ }
+
+ /**
+ * Load the sound from a resource.
+ */
+ public void loadSound(int resourceId) {
+ int soundId = mSoundPool.load(mAppContext, resourceId, 1/* priority */);
+ mResourceToSoundId.put(resourceId, soundId);
+ }
+
+ /**
+ * Play the sound with the given resource. The resource has to be loaded
+ * before it can be played, otherwise an exception will be thrown.
+ */
+ public void play(int resourceId, float volume) {
+ Integer soundId = mResourceToSoundId.get(resourceId);
+ if (soundId == null) {
+ throw new IllegalStateException("Sound not loaded. Must call #loadSound first.");
+ }
+ mSoundPool.play(soundId, volume, volume, 0 /* priority */, 0 /* loop */, 1 /* rate */);
+ }
+
+ /**
+ * Unload the given sound if it's not needed anymore to release memory.
+ */
+ public void unloadSound(int resourceId) {
+ Integer soundId = mResourceToSoundId.get(resourceId);
+ if (soundId == null) {
+ throw new IllegalStateException("Sound not loaded. Must call #loadSound first.");
+ }
+ mSoundPool.unload(soundId);
+ }
+
+ /**
+ * Call this if you don't need the SoundPlayer anymore. All memory will be
+ * released and the object cannot be re-used.
+ */
+ public void release() {
+ mIsReleased = true;
+ mSoundPool.release();
+ }
+
+ public boolean isReleased() {
+ return mIsReleased;
+ }
+
+ private static int getAudioTypeForSoundPool() {
+ // STREAM_SYSTEM_ENFORCED is hidden API.
+ return ApiHelper.getIntFieldIfExists(AudioManager.class,
+ "STREAM_SYSTEM_ENFORCED", null, AudioManager.STREAM_RING);
+ }
+}
diff --git a/src/com/android/camera/VideoController.java b/src/com/android/camera/VideoController.java
index cf694a391..a5b92c1f4 100644
--- a/src/com/android/camera/VideoController.java
+++ b/src/com/android/camera/VideoController.java
@@ -40,4 +40,6 @@ public interface VideoController extends OnShutterButtonListener, OnPauseButtonL
// Callbacks for camera preview UI events.
public void onPreviewUIReady();
public void onPreviewUIDestroyed();
+
+ public void onScreenSizeChanged(int width, int height);
}
diff --git a/src/com/android/camera/VideoMenu.java b/src/com/android/camera/VideoMenu.java
index ca6aa0687..6baa71c24 100644
--- a/src/com/android/camera/VideoMenu.java
+++ b/src/com/android/camera/VideoMenu.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013-2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -77,6 +78,7 @@ public class VideoMenu extends MenuController
private static final int PREVIEW_MENU_IN_ANIMATION = 1;
private static final int PREVIEW_MENU_ON = 2;
private static final int MODE_FILTER = 1;
+ private static final int DEVELOPER_MENU_TOUCH_COUNT = 7;
private int mSceneStatus;
private View mFrontBackSwitcher;
private View mFilterModeSwitcher;
@@ -86,6 +88,7 @@ public class VideoMenu extends MenuController
private String mPrevSavedVideoCDS;
private boolean mIsVideoTNREnabled = false;
private boolean mIsVideoCDSUpdated = false;
+ private int mPrivateCounter = 0;
private static final int ANIMATION_DURATION = 300;
private static final int CLICK_THRESHOLD = 200;
private int previewMenuSize;
@@ -111,23 +114,32 @@ public class VideoMenu extends MenuController
// settings popup
mOtherKeys1 = new String[] {
CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE,
- CameraSettings.KEY_VIDEO_QUALITY,
- CameraSettings.KEY_VIDEO_DURATION,
CameraSettings.KEY_RECORD_LOCATION,
+ CameraSettings.KEY_VIDEO_QUALITY,
CameraSettings.KEY_CAMERA_SAVEPATH,
+ CameraSettings.KEY_EXPOSURE,
CameraSettings.KEY_WHITE_BALANCE,
+ CameraSettings.KEY_VIDEOCAMERA_FOCUS_MODE,
+ CameraSettings.KEY_VIDEOCAMERA_FOCUS_TIME,
CameraSettings.KEY_VIDEO_HIGH_FRAME_RATE,
- CameraSettings.KEY_DIS
+ CameraSettings.KEY_DIS,
+ CameraSettings.KEY_POWER_SHUTTER,
+ CameraSettings.KEY_MAX_BRIGHTNESS
};
mOtherKeys2 = new String[] {
CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE,
- CameraSettings.KEY_VIDEO_QUALITY,
- CameraSettings.KEY_VIDEO_DURATION,
CameraSettings.KEY_RECORD_LOCATION,
+ CameraSettings.KEY_VIDEO_QUALITY,
+ CameraSettings.KEY_VIDEO_SNAPSHOT_SIZE,
CameraSettings.KEY_CAMERA_SAVEPATH,
- CameraSettings.KEY_WHITE_BALANCE,
CameraSettings.KEY_FACE_DETECTION,
+ CameraSettings.KEY_EXPOSURE,
+ CameraSettings.KEY_WHITE_BALANCE,
+ CameraSettings.KEY_VIDEOCAMERA_FOCUS_MODE,
+ CameraSettings.KEY_VIDEOCAMERA_FOCUS_TIME,
CameraSettings.KEY_VIDEO_HIGH_FRAME_RATE,
+ CameraSettings.KEY_POWER_SHUTTER,
+ CameraSettings.KEY_MAX_BRIGHTNESS,
CameraSettings.KEY_SEE_MORE,
CameraSettings.KEY_NOISE_REDUCTION,
CameraSettings.KEY_DIS,
@@ -136,6 +148,7 @@ public class VideoMenu extends MenuController
CameraSettings.KEY_VIDEO_ENCODER,
CameraSettings.KEY_AUDIO_ENCODER,
CameraSettings.KEY_VIDEO_HDR,
+ CameraSettings.KEY_ANTIBANDING,
CameraSettings.KEY_POWER_MODE,
CameraSettings.KEY_VIDEO_ROTATION,
CameraSettings.KEY_VIDEO_CDS_MODE,
@@ -308,7 +321,7 @@ public class VideoMenu extends MenuController
public void animateFadeIn(final ListView v) {
ViewPropertyAnimator vp = v.animate();
- vp.alpha(0.85f).setDuration(ANIMATION_DURATION);
+ vp.alpha(1f).setDuration(ANIMATION_DURATION);
vp.start();
}
@@ -476,6 +489,7 @@ public class VideoMenu extends MenuController
return;
}
// Each entry has a corresponding icon.
+ index = index % iconIds.length;
resid = iconIds[index];
} else {
// The preference only has a single icon to represent it.
@@ -495,8 +509,9 @@ public class VideoMenu extends MenuController
CharSequence[] values = pref.getEntryValues();
index = (index + 1) % values.length;
pref.setValueIndex(index);
+ int iconListLength = ((IconListPreference) pref).getLargeIconIds().length;
((ImageView) v).setImageResource(
- ((IconListPreference) pref).getLargeIconIds()[index]);
+ ((IconListPreference) pref).getLargeIconIds()[index % iconListLength]);
if (prefKey.equals(CameraSettings.KEY_CAMERA_ID))
mListener.onCameraPickerClicked(index);
reloadPreference(pref);
@@ -508,7 +523,7 @@ public class VideoMenu extends MenuController
public void initFilterModeButton(View button) {
button.setVisibility(View.INVISIBLE);
final IconListPreference pref = (IconListPreference) mPreferenceGroup
- .findPreference(CameraSettings.KEY_COLOR_EFFECT);
+ .findPreference(CameraSettings.KEY_VIDEOCAMERA_COLOR_EFFECT);
if (pref == null || pref.getValue() == null)
return;
@@ -536,7 +551,7 @@ public class VideoMenu extends MenuController
public void addFilterMode() {
final IconListPreference pref = (IconListPreference) mPreferenceGroup
- .findPreference(CameraSettings.KEY_COLOR_EFFECT);
+ .findPreference(CameraSettings.KEY_VIDEOCAMERA_COLOR_EFFECT);
if (pref == null)
return;
@@ -615,10 +630,8 @@ public class VideoMenu extends MenuController
pref.setValueIndex(j);
changeFilterModeControlIcon(pref.getValue());
for (View v1 : views) {
- v1.setBackground(null);
+ v1.setActivated(v1 == v);
}
- ImageView image = (ImageView) v.findViewById(R.id.image);
- image.setBackgroundColor(0xff33b5e5);
onSettingChanged(pref);
}
@@ -627,9 +640,8 @@ public class VideoMenu extends MenuController
}
});
- views[j] = imageView;
- if (i == init)
- imageView.setBackgroundColor(0xff33b5e5);
+ views[j] = layout2;
+ layout2.setActivated(i == init);
TextView label = (TextView) layout2.findViewById(R.id.label);
imageView.setImageResource(thumbnails[i]);
label.setText(entries[i]);
@@ -796,6 +808,8 @@ public class VideoMenu extends MenuController
|| !videoHDR.equals("off")
|| timeLapseInterval != 0) {
mListMenu.setPreferenceEnabled(CameraSettings.KEY_VIDEO_HIGH_FRAME_RATE, false);
+ RotateTextToast.makeText(mActivity, R.string.error_app_unsupported_hfr_selection,
+ Toast.LENGTH_LONG).show();
}
}
@@ -889,6 +903,31 @@ public class VideoMenu extends MenuController
mUI.showPopup(mListSubMenu, 2, true);
}
mPopupStatus = POPUP_SECOND_LEVEL;
+
+ // Developer menu
+ if (pref.getKey().equals(CameraSettings.KEY_MAX_BRIGHTNESS)) {
+ mPrivateCounter++;
+ if (mPrivateCounter >= DEVELOPER_MENU_TOUCH_COUNT) {
+ SharedPreferences prefs = PreferenceManager
+ .getDefaultSharedPreferences(mActivity);
+ if (!mActivity.isDeveloperMenuEnabled()) {
+ mActivity.enableDeveloperMenu();
+ prefs.edit().putBoolean(CameraSettings.KEY_DEVELOPER_MENU, true).apply();
+ closeAllView();
+ RotateTextToast.makeText(mActivity,
+ R.string.developer_menu_enabled, Toast.LENGTH_SHORT).show();
+ } else {
+ mActivity.disableDeveloperMenu();
+ prefs.edit().putBoolean(CameraSettings.KEY_DEVELOPER_MENU, false).apply();
+ closeAllView();
+ RotateTextToast.makeText(mActivity,
+ R.string.developer_menu_disabled, Toast.LENGTH_SHORT).show();
+ }
+ mPrivateCounter = 0;
+ }
+ } else {
+ mPrivateCounter = 0;
+ }
}
public void onListMenuTouched() {
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index fc65eb5bc..190cc248a 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013-2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,6 +61,7 @@ import android.widget.Toast;
import android.media.EncoderCapabilities;
import android.media.EncoderCapabilities.VideoEncoderCap;
+import com.android.camera.CameraManager.CameraAFCallback;
import com.android.camera.CameraManager.CameraPictureCallback;
import com.android.camera.CameraManager.CameraProxy;
import com.android.camera.app.OrientationManager;
@@ -88,6 +90,7 @@ import java.util.regex.Pattern;
public class VideoModule implements CameraModule,
VideoController,
+ FocusOverlayManager.Listener,
CameraPreference.OnPreferenceChangedListener,
ShutterButton.OnShutterButtonListener,
LocationManager.Listener,
@@ -104,6 +107,7 @@ public class VideoModule implements CameraModule,
private static final int SWITCH_CAMERA = 8;
private static final int SWITCH_CAMERA_START_ANIMATION = 9;
private static final int HANDLE_FLASH_TORCH_DELAY = 10;
+ private static final int SET_FOCUS_RATIO = 11;
private static final int SCREEN_DELAY = 2 * 60 * 1000;
@@ -124,6 +128,10 @@ public class VideoModule implements CameraModule,
private boolean mPaused;
private int mCameraId;
private Parameters mParameters;
+ private boolean mFocusAreaSupported;
+ private boolean mMeteringAreaSupported;
+ private boolean mAeLockSupported;
+ private boolean mAwbLockSupported;
private boolean mIsInReviewMode;
private boolean mSnapshotInProgress = false;
@@ -177,11 +185,18 @@ public class VideoModule implements CameraModule,
// true.
private int mDisplayRotation;
private int mCameraDisplayOrientation;
+ private int mOrientationOffset;
private int mDesiredPreviewWidth;
private int mDesiredPreviewHeight;
private ContentResolver mContentResolver;
+ private final AutoFocusCallback mAutoFocusCallback =
+ new AutoFocusCallback();
+
+ // This handles everything about focus.
+ private FocusOverlayManager mFocusManager;
+
private LocationManager mLocationManager;
private OrientationManager mOrientationManager;
private int mPendingSwitchCameraId;
@@ -270,6 +285,7 @@ public class VideoModule implements CameraModule,
@Override
public void run() {
openCamera();
+ if (mFocusManager == null) initializeFocusManager();
}
}
@@ -284,6 +300,7 @@ public class VideoModule implements CameraModule,
return;
}
mParameters = mCameraDevice.getParameters();
+ initializeCapabilities();
mPreviewFocused = arePreviewControlsVisible();
}
@@ -361,9 +378,12 @@ public class VideoModule implements CameraModule,
private boolean mUnsupportedHFRVideoSize = false;
private boolean mUnsupportedHSRVideoSize = false;
private boolean mUnsupportedHFRVideoCodec = false;
- private String mDefaultAntibanding = null;
boolean mUnsupportedProfile = false;
+ public void onScreenSizeChanged(int width, int height) {
+ if (mFocusManager != null) mFocusManager.setPreviewSize(width, height);
+ }
+
// This Handler is used to post message back onto the main thread of the
// application
private class MainHandler extends Handler {
@@ -426,6 +446,11 @@ public class VideoModule implements CameraModule,
break;
}
+ case SET_FOCUS_RATIO: {
+ mUI.getFocusRing().setRadiusRatio((Float)msg.obj);
+ break;
+ }
+
default:
Log.v(TAG, "Unhandled message: " + msg.what);
break;
@@ -490,6 +515,8 @@ public class VideoModule implements CameraModule,
public void init(CameraActivity activity, View root) {
mActivity = activity;
mUI = new VideoUI(activity, this, root);
+ mOrientationOffset = CameraUtil.isDefaultToPortrait(mActivity) ? 0 : 90;
+
mPreferences = ComboPreferences.get(mActivity);
if (mPreferences == null) {
mPreferences = new ComboPreferences(mActivity);
@@ -500,9 +527,17 @@ public class VideoModule implements CameraModule,
mPreferences.setLocalId(mActivity, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
+ // we need to reset exposure for the preview
+ resetExposureCompensation();
mOrientationManager = new OrientationManager(mActivity);
+ // Power shutter
+ mActivity.initPowerShutter(mPreferences);
+
+ // Max brightness
+ mActivity.initMaxBrightness(mPreferences);
+
/*
* To reduce startup time, we start the preview in another thread.
* We make sure the preview is started at the end of onCreate.
@@ -547,6 +582,20 @@ public class VideoModule implements CameraModule,
mPendingSwitchCameraId = -1;
}
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+ private void setAutoExposureLockIfSupported() {
+ if (mAeLockSupported) {
+ mParameters.setAutoExposureLock(mFocusManager.getAeAwbLock());
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+ private void setAutoWhiteBalanceLockIfSupported() {
+ if (mAwbLockSupported) {
+ mParameters.setAutoWhiteBalanceLock(mFocusManager.getAeAwbLock());
+ }
+ }
+
@Override
public void waitingLocationPermissionResult(boolean result) {
mLocationManager.waitingLocationPermissionResult(result);
@@ -565,6 +614,38 @@ public class VideoModule implements CameraModule,
}
@Override
+ public void autoFocus() {
+ Log.e(TAG, "start autoFocus.");
+ mCameraDevice.autoFocus(mHandler, mAutoFocusCallback);
+ }
+
+ @Override
+ public void cancelAutoFocus() {
+ if (null != mCameraDevice) {
+ setFocusParameters();
+ }
+ }
+
+ @Override
+ public boolean capture() {
+ return true;
+ }
+
+ @Override
+ public void setFocusParameters() {
+ if (mFocusAreaSupported)
+ mParameters.setFocusAreas(mFocusManager.getFocusAreas());
+ if (mMeteringAreaSupported)
+ mParameters.setMeteringAreas(mFocusManager.getMeteringAreas());
+ setAutoExposureLockIfSupported();
+ setAutoWhiteBalanceLockIfSupported();
+ if (mFocusAreaSupported || mMeteringAreaSupported) {
+ mParameters.setFocusMode(mFocusManager.getFocusMode(true));
+ mCameraDevice.setParameters(mParameters);
+ }
+ }
+
+ @Override
public void setPreferenceForTest(String key, String value) {
mUI.setPreference(key, value);
onSharedPreferenceChanged();
@@ -575,22 +656,34 @@ public class VideoModule implements CameraModule,
@Override
public void onSingleTapUp(View view, int x, int y) {
if (mMediaRecorderPausing) return;
- takeASnapshot();
+ boolean snapped = takeASnapshot();
+ if (!snapped) {
+ // Do not trigger touch focus if popup window is opened.
+ if (mUI.removeTopLevelPopup()) {
+ return;
+ }
+
+ // Check if metering area or focus area is supported.
+ if ((mFocusAreaSupported || mMeteringAreaSupported) && !mSnapshotInProgress) {
+ mFocusManager.onSingleTapUp(x, y);
+ }
+ }
}
- private void takeASnapshot() {
+ private boolean takeASnapshot() {
// Only take snapshots if video snapshot is supported by device
if (CameraUtil.isVideoSnapshotSupported(mParameters) && !mIsVideoCaptureIntent) {
if (!mMediaRecorderRecording || mPaused || mSnapshotInProgress) {
- return;
+ return false;
}
MediaSaveService s = mActivity.getMediaSaveService();
if (s == null || s.isQueueFull()) {
- return;
+ return false;
}
// Set rotation and gps data.
- int rotation = CameraUtil.getJpegRotation(mCameraId, mOrientation);
+ int orientation = (mOrientation + mOrientationOffset) % 360;
+ int rotation = CameraUtil.getJpegRotation(mCameraId, orientation);
mParameters.setRotation(rotation);
Location loc = mLocationManager.getCurrentLocation();
CameraUtil.setGpsParameters(mParameters, loc);
@@ -603,7 +696,10 @@ public class VideoModule implements CameraModule,
mSnapshotInProgress = true;
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_CAPTURE_DONE, "VideoSnapshot");
+
+ return true;
}
+ return false;
}
@Override
@@ -619,7 +715,7 @@ public class VideoModule implements CameraModule,
mPreferenceGroup = filterPreferenceScreenByIntent(
settings.getPreferenceGroup(R.xml.video_preferences));
- int numOfCams = Camera.getNumberOfCameras();
+ int numOfCams = CameraHolder.instance().getNumberOfCameras();
//TODO: If numOfCams > 2 then corresponding entries needs to be added to the media_profiles.xml
@@ -639,8 +735,8 @@ public class VideoModule implements CameraModule,
int[] largeIconIds = new int[numOfCams];
for(int i=0;i<numOfCams;i++) {
- CameraInfo info = CameraHolder.instance().getCameraInfo()[i];
- if(info.facing == CameraInfo.CAMERA_FACING_BACK) {
+ CameraHolder.CameraInfo info = CameraHolder.instance().getCameraInfo()[i];
+ if(info.facing == CameraHolder.CameraInfo.CAMERA_FACING_BACK) {
iconIds[i] = R.drawable.ic_switch_back;
entries[i] = mActivity.getResources().getString(R.string.pref_camera_id_entry_back);
labels[i] = mActivity.getResources().getString(R.string.pref_camera_id_label_back);
@@ -671,6 +767,7 @@ public class VideoModule implements CameraModule,
// the camera then point the camera to floor or sky, we still have
// the correct orientation.
if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) return;
+ orientation = (orientation - mOrientationOffset + 360) % 360;
int newOrientation = CameraUtil.roundOrientation(orientation, mOrientation);
if (mOrientation != newOrientation) {
@@ -695,6 +792,7 @@ public class VideoModule implements CameraModule,
private void startPlayVideoActivity() {
Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(mCurrentVideoUri, convertOutputFormatToMimeType(mProfile.fileFormat));
try {
mActivity
@@ -840,24 +938,6 @@ public class VideoModule implements CameraModule,
Log.v(TAG, "Audio Encoder selected = " +mAudioEncoder);
- String minutesStr = mPreferences.getString(
- CameraSettings.KEY_VIDEO_DURATION,
- mActivity.getString(R.string.pref_camera_video_duration_default));
- int minutes = -1;
- try {
- minutes = Integer.parseInt(minutesStr);
- } catch(NumberFormatException npe) {
- // use default value continue
- minutes = Integer.parseInt(mActivity.getString(
- R.string.pref_camera_video_duration_default));
- }
- if (minutes == -1) {
- // User wants lowest, set 30s */
- mMaxVideoDurationInMs = 30000;
- } else {
- // 1 minute = 60000ms
- mMaxVideoDurationInMs = 60000 * minutes;
- }
if(ParametersWrapper.isPowerModeSupported(mParameters)) {
String powermode = mPreferences.getString(
CameraSettings.KEY_POWER_MODE,
@@ -878,12 +958,34 @@ public class VideoModule implements CameraModule,
}
}
+ private final class AutoFocusCallback
+ implements CameraAFCallback {
+ @Override
+ public void onAutoFocus(
+ boolean focused, CameraProxy camera) {
+ Log.v(TAG, "AutoFocusCallback, mPaused=" + mPaused);
+ if (mPaused) return;
+
+ //setCameraState(IDLE);
+ mCameraDevice.refreshParameters();
+ mFocusManager.setParameters(mCameraDevice.getParameters());
+ mFocusManager.onAutoFocus(focused, false);
+ }
+ }
+
+ @Override
+ public void setFocusRatio(float ratio) {
+ mHandler.removeMessages(SET_FOCUS_RATIO);
+ Message m = mHandler.obtainMessage(SET_FOCUS_RATIO);
+ m.obj = ratio;
+ mHandler.sendMessage(m);
+ }
+
private void readVideoPreferences() {
// The preference stores values from ListPreference and is thus string type for all values.
// We need to convert it to int manually.
- String videoQuality = mPreferences.getString(CameraSettings.KEY_VIDEO_QUALITY,
- null);
- if (videoQuality == null) {
+ String videoQuality = mPreferences.getString(CameraSettings.KEY_VIDEO_QUALITY, null);
+ if (videoQuality == null || (videoQuality.length() < 3 && !videoQuality.contains("x"))) {
mParameters = mCameraDevice.getParameters();
String defaultQuality = mActivity.getResources().getString(
R.string.pref_video_quality_default);
@@ -895,7 +997,7 @@ public class VideoModule implements CameraModule,
} else {
// check for highest quality supported
videoQuality = CameraSettings.getSupportedHighestVideoQuality(
- mCameraId, mParameters);
+ mActivity, mCameraId, mParameters);
}
mPreferences.edit().putString(CameraSettings.KEY_VIDEO_QUALITY, videoQuality).apply();
}
@@ -1088,8 +1190,18 @@ public class VideoModule implements CameraModule,
". mDesiredPreviewHeight=" + mDesiredPreviewHeight);
}
+ private void resetExposureCompensation() {
+ String value = mPreferences.getString(CameraSettings.KEY_EXPOSURE,
+ CameraSettings.EXPOSURE_DEFAULT_VALUE);
+ if (!CameraSettings.EXPOSURE_DEFAULT_VALUE.equals(value)) {
+ Editor editor = mPreferences.edit();
+ editor.putString(CameraSettings.KEY_EXPOSURE, "0");
+ editor.apply();
+ }
+ }
+
void setPreviewFrameLayoutCameraOrientation(){
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+ CameraHolder.CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
//if camera mount angle is 0 or 180, we want to resize preview
if (info.orientation % 180 == 0)
@@ -1129,6 +1241,7 @@ public class VideoModule implements CameraModule,
@Override
public void onResumeBeforeSuper() {
mPaused = false;
+ if (mFocusManager == null) initializeFocusManager();
}
@Override
@@ -1141,6 +1254,7 @@ public class VideoModule implements CameraModule,
if(mWasMute != mIsMute) {
setMute(mIsMute, false);
}
+ resetExposureCompensation();
showVideoSnapshotUI(false);
installIntentFilter();
@@ -1191,6 +1305,9 @@ public class VideoModule implements CameraModule,
private void setDisplayOrientation() {
mDisplayRotation = CameraUtil.getDisplayRotation(mActivity);
mCameraDisplayOrientation = CameraUtil.getDisplayOrientation(mDisplayRotation, mCameraId);
+ if (mFocusManager != null) {
+ mFocusManager.setDisplayOrientation(mCameraDisplayOrientation);
+ }
mUI.setDisplayOrientation(mCameraDisplayOrientation);
// Change the camera display orientation
if (mCameraDevice != null) {
@@ -1259,6 +1376,8 @@ public class VideoModule implements CameraModule,
throw new RuntimeException("startPreview failed", ex);
}
mStartPrevPending = false;
+
+ mFocusManager.onPreviewStarted();
}
private void onPreviewStarted() {
@@ -1270,6 +1389,8 @@ public class VideoModule implements CameraModule,
public void stopPreview() {
mStopPrevPending = true;
+ if (mFocusManager != null) mFocusManager.onPreviewStopped();
+
if (!mPreviewing) {
mStopPrevPending = false;
return;
@@ -1298,6 +1419,7 @@ public class VideoModule implements CameraModule,
mCameraDevice = null;
mPreviewing = false;
mSnapshotInProgress = false;
+ mFocusManager.onCameraReleased();
mPreviewFocused = false;
mFaceDetectionStarted = false;
}
@@ -1355,6 +1477,28 @@ public class VideoModule implements CameraModule,
@Override
public void onPauseAfterSuper() {
+ if (mFocusManager != null) mFocusManager.removeMessages();
+ }
+
+ /**
+ * The focus manager is the first UI related element to get initialized,
+ * and it requires the RenderOverlay, so initialize it here
+ */
+ private void initializeFocusManager() {
+ // Create FocusManager object. startPreview needs it.
+ // if mFocusManager not null, reuse it
+ // otherwise create a new instance
+ if (mFocusManager != null) {
+ mFocusManager.removeMessages();
+ } else {
+ CameraHolder.CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+ boolean mirror = (info.facing == CameraHolder.CameraInfo.CAMERA_FACING_FRONT);
+ String[] defaultFocusModes = mActivity.getResources().getStringArray(
+ R.array.pref_video_focusmode_default_array);
+ mFocusManager = new FocusOverlayManager(mPreferences, defaultFocusModes,
+ mParameters, this, mirror,
+ mActivity.getMainLooper(), mUI.getFocusRing(), mActivity);
+ }
}
@Override
@@ -1385,20 +1529,45 @@ public class VideoModule implements CameraModule,
}
switch (keyCode) {
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_MEDIA_NEXT:
+ if (event.getRepeatCount() == 0 && !CameraActivity.mPowerShutter &&
+ !CameraUtil.hasCameraKey()) {
+ mUI.clickShutter();
+ } else {
+ mUI.onScaleStepResize(true);
+ }
+ return true;
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+ if (event.getRepeatCount() == 0 && !CameraActivity.mPowerShutter &&
+ !CameraUtil.hasCameraKey()) {
+ mUI.clickShutter();
+ } else {
+ mUI.onScaleStepResize(false);
+ }
+ return true;
case KeyEvent.KEYCODE_CAMERA:
+ case KeyEvent.KEYCODE_HEADSETHOOK:
if (event.getRepeatCount() == 0) {
mUI.clickShutter();
- return true;
}
- break;
+ return true;
case KeyEvent.KEYCODE_DPAD_CENTER:
if (event.getRepeatCount() == 0) {
mUI.clickShutter();
- return true;
}
- break;
+ return true;
+ case KeyEvent.KEYCODE_POWER:
+ if (event.getRepeatCount() == 0 && CameraActivity.mPowerShutter &&
+ !CameraUtil.hasCameraKey()) {
+ mUI.clickShutter();
+ }
+ return true;
case KeyEvent.KEYCODE_MENU:
- if (mMediaRecorderRecording) return true;
+ if (mMediaRecorderRecording) {
+ return true;
+ }
break;
}
return false;
@@ -1407,9 +1576,27 @@ public class VideoModule implements CameraModule,
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_MEDIA_NEXT:
+ if (!CameraActivity.mPowerShutter && !CameraUtil.hasCameraKey()) {
+ mUI.pressShutter(false);
+ }
+ return true;
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+ if (!CameraActivity.mPowerShutter && !CameraUtil.hasCameraKey()) {
+ mUI.pressShutter(false);
+ }
+ return true;
case KeyEvent.KEYCODE_CAMERA:
+ case KeyEvent.KEYCODE_HEADSETHOOK:
mUI.pressShutter(false);
return true;
+ case KeyEvent.KEYCODE_POWER:
+ if (CameraActivity.mPowerShutter && !CameraUtil.hasCameraKey()) {
+ mUI.pressShutter(false);
+ }
+ return true;
}
return false;
}
@@ -1445,6 +1632,7 @@ public class VideoModule implements CameraModule,
}
private void setupMediaRecorderPreviewDisplay() {
+ mFocusManager.resetTouchFocus();
// Nothing to do here if using SurfaceTexture.
if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) {
// We stop the preview here before unlocking the device because we
@@ -1582,7 +1770,8 @@ public class VideoModule implements CameraModule,
}
mMediaRecorder.setOutputFormat(mProfile.fileFormat);
mMediaRecorder.setVideoFrameRate(mProfile.videoFrameRate);
- mMediaRecorder.setVideoEncodingBitRate(mProfile.videoBitRate);
+ mMediaRecorder.setVideoEncodingBitRate(mProfile.videoBitRate *
+ ((isHSR ? captureRate : 30) / 30));
mMediaRecorder.setVideoEncoder(mProfile.videoCodec);
if (isHSR) {
Log.i(TAG, "Configuring audio for HSR");
@@ -1620,7 +1809,11 @@ public class VideoModule implements CameraModule,
// In case framerate is different, scale the bitrate
int scaledBitrate = getHighSpeedVideoEncoderBitRate(mProfile, targetFrameRate);
Log.i(TAG, "Scaled Video bitrate : " + scaledBitrate);
- mMediaRecorder.setVideoEncodingBitRate(scaledBitrate);
+ if (scaledBitrate > 0) {
+ mMediaRecorder.setVideoEncodingBitRate(scaledBitrate);
+ } else {
+ Log.e(TAG, "Cannot set Video bitrate because its negative");
+ }
}
setRecordLocation();
@@ -1661,11 +1854,11 @@ public class VideoModule implements CameraModule,
// 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];
- if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
- rotation = (info.orientation - mOrientation + 360) % 360;
+ CameraHolder.CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+ if (info.facing == CameraHolder.CameraInfo.CAMERA_FACING_FRONT) {
+ rotation = (info.orientation - mOrientation - mOrientationOffset + 360) % 360;
} else { // back-facing camera
- rotation = (info.orientation + mOrientation) % 360;
+ rotation = (info.orientation + mOrientation + mOrientationOffset) % 360;
}
}
mMediaRecorder.setOrientationHint(rotation);
@@ -1851,7 +2044,6 @@ public class VideoModule implements CameraModule,
mStartRecPending = true;
mUI.cancelAnimations();
mUI.setSwipingEnabled(false);
- mUI.hideUIwhileRecording();
// When recording request is sent before starting preview, onPreviewFrame()
// callback doesn't happen so removing preview cover here, instead.
if (mUI.isPreviewCoverVisible()) {
@@ -1924,6 +2116,8 @@ public class VideoModule implements CameraModule,
return false;
}
+ mUI.hideUIwhileRecording();
+
// Make sure the video recording has started before announcing
// this in accessibility.
AccessibilityUtils.makeAnnouncement(mUI.getShutterButton(),
@@ -1974,8 +2168,8 @@ public class VideoModule implements CameraModule,
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();
- boolean mirror = (info[mCameraId].facing == CameraInfo.CAMERA_FACING_FRONT);
+ CameraHolder.CameraInfo[] info = CameraHolder.instance().getCameraInfo();
+ boolean mirror = (info[mCameraId].facing == CameraHolder.CameraInfo.CAMERA_FACING_FRONT);
bitmap = CameraUtil.rotateAndMirror(bitmap, 0, mirror);
}
return bitmap;
@@ -2085,6 +2279,16 @@ public class VideoModule implements CameraModule,
mUI.hideSurfaceView();
// Switch back to use SurfaceTexture for preview.
startPreview();
+ } else {
+ if (is4KEnabled()) {
+ int fps = CameraUtil.getMaxPreviewFps(mParameters);
+ if (fps > 0) {
+ mParameters.setPreviewFrameRate(fps);
+ } else {
+ mParameters.setPreviewFrameRate(30);
+ }
+ mCameraDevice.setParameters(mParameters);
+ }
}
}
// Update the parameters here because the parameters might have been altered
@@ -2338,7 +2542,7 @@ public class VideoModule implements CameraModule,
setZoomMenuValue();
String colorEffect = mPreferences.getString(
- CameraSettings.KEY_COLOR_EFFECT,
+ CameraSettings.KEY_VIDEOCAMERA_COLOR_EFFECT,
mActivity.getString(R.string.pref_camera_coloreffect_default));
Log.v(TAG, "Color effect value =" + colorEffect);
if (isSupported(colorEffect, mParameters.getSupportedColorEffects())) {
@@ -2372,22 +2576,14 @@ public class VideoModule implements CameraModule,
}
}
- if (mDefaultAntibanding == null) {
- mDefaultAntibanding = mParameters.getAntibanding();
- Log.d(TAG, "default antibanding value = " + mDefaultAntibanding);
- }
-
- if (disMode.equals("enable")) {
- Log.d(TAG, "dis is enabled, set antibanding to auto.");
- if (isSupported(Parameters.ANTIBANDING_AUTO, mParameters.getSupportedAntibanding())) {
- mParameters.setAntibanding(Parameters.ANTIBANDING_AUTO);
- }
- } else {
- if (isSupported(mDefaultAntibanding, mParameters.getSupportedAntibanding())) {
- mParameters.setAntibanding(mDefaultAntibanding);
- }
+ // Set anti banding parameter.
+ String antiBanding = mPreferences.getString(
+ CameraSettings.KEY_ANTIBANDING,
+ mActivity.getString(R.string.pref_camera_antibanding_default));
+ Log.v(TAG, "antiBanding value =" + antiBanding);
+ if (CameraUtil.isSupported(antiBanding, mParameters.getSupportedAntibanding())) {
+ mParameters.setAntibanding(antiBanding);
}
- Log.d(TAG, "antiBanding value = " + mParameters.getAntibanding());
mUnsupportedHFRVideoSize = false;
mUnsupportedHFRVideoCodec = false;
@@ -2671,6 +2867,14 @@ public class VideoModule implements CameraModule,
//set power mode settings
updatePowerMode();
+ // Set focus mode
+ mParameters.setFocusMode(mFocusManager.getFocusMode(true));
+
+ // Set focus time.
+ mFocusManager.setFocusTime(Integer.decode(
+ mPreferences.getString(CameraSettings.KEY_VIDEOCAMERA_FOCUS_TIME,
+ mActivity.getString(R.string.pref_camera_video_focustime_default))));
+
// Set face detetction parameter.
String faceDetection = mPreferences.getString(
CameraSettings.KEY_FACE_DETECTION,
@@ -2721,7 +2925,18 @@ public class VideoModule implements CameraModule,
Log.i(TAG,"NOTE: SetCameraParameters " + videoWidth + " x " + videoHeight);
String recordSize = videoWidth + "x" + videoHeight;
Log.e(TAG,"Video dimension in App->"+recordSize);
- mParameters.set("video-size", recordSize);
+ if (CameraUtil.isSupported(mParameters, "video-size")) {
+ mParameters.set("video-size", recordSize);
+ }
+ // Set exposure compensation
+ int value = CameraSettings.readExposure(mPreferences);
+ int max = mParameters.getMaxExposureCompensation();
+ int min = mParameters.getMinExposureCompensation();
+ if (value >= min && value <= max) {
+ mParameters.setExposureCompensation(value);
+ } else {
+ Log.w(TAG, "invalid exposure range: " + value);
+ }
// Set white balance parameter.
String whiteBalance = mPreferences.getString(
CameraSettings.KEY_WHITE_BALANCE,
@@ -2744,10 +2959,8 @@ public class VideoModule implements CameraModule,
}
// Set continuous autofocus.
- List<String> supportedFocus = mParameters.getSupportedFocusModes();
- if (isSupported(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO, supportedFocus)) {
- mParameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
- }
+ // Set focus mode
+ mParameters.setFocusMode(mFocusManager.getFocusMode(true));
mParameters.set(CameraUtil.RECORDING_HINT, CameraUtil.TRUE);
@@ -2802,6 +3015,9 @@ public class VideoModule implements CameraModule,
int jpegQuality = CameraProfile.getJpegEncodingQualityParameter(mCameraId,
CameraProfile.QUALITY_HIGH);
mParameters.setJpegQuality(jpegQuality);
+
+ CameraUtil.dumpParameters(mParameters);
+
//Call Qcom related Camera Parameters
qcomSetCameraParameters();
@@ -2817,8 +3033,7 @@ public class VideoModule implements CameraModule,
// Keep preview size up to date.
mParameters = mCameraDevice.getParameters();
- // Update UI based on the new parameters.
- mUI.updateOnScreenIndicators(mParameters, mPreferences);
+ mFocusManager.setPreviewSize(videoWidth, videoHeight);
}
@Override
@@ -2893,10 +3108,11 @@ public class VideoModule implements CameraModule,
setCameraParameters(false);
}
mRestartPreview = false;
- mUI.updateOnScreenIndicators(mParameters, mPreferences);
Storage.setSaveSDCard(
mPreferences.getString(CameraSettings.KEY_CAMERA_SAVEPATH, "0").equals("1"));
mActivity.updateStorageSpaceAndHint();
+ mActivity.initPowerShutter(mPreferences);
+ mActivity.initMaxBrightness(mPreferences);
}
}
@@ -2918,10 +3134,18 @@ public class VideoModule implements CameraModule,
closeCamera();
mUI.collapseCameraControls();
+ if (mFocusManager != null) mFocusManager.removeMessages();
// Restart the camera and initialize the UI. From onCreate.
mPreferences.setLocalId(mActivity, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
openCamera();
+
+ CameraHolder.CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+ boolean mirror = (info.facing == CameraHolder.CameraInfo.CAMERA_FACING_FRONT);
+ mParameters = mCameraDevice.getParameters();
+ mFocusManager.setMirror(mirror);
+ mFocusManager.setParameters(mParameters);
+
readVideoPreferences();
mUI.applySurfaceChange(VideoUI.SURFACE_STATUS.SURFACE_VIEW);
startPreview();
@@ -2929,6 +3153,8 @@ public class VideoModule implements CameraModule,
resizeForPreviewAspectRatio();
initializeVideoControl();
+ initializeCapabilities();
+
// From onResume
mZoomValue = 0;
mUI.initializeZoom(mParameters);
@@ -2937,12 +3163,18 @@ public class VideoModule implements CameraModule,
// Start switch camera animation. Post a message because
// onFrameAvailable from the old camera may already exist.
mHandler.sendEmptyMessage(SWITCH_CAMERA_START_ANIMATION);
- mUI.updateOnScreenIndicators(mParameters, mPreferences);
//Display timelapse msg depending upon selection in front/back camera.
mUI.showTimeLapseUI(mCaptureTimeLapse);
}
+ private void initializeCapabilities() {
+ mFocusAreaSupported = CameraUtil.isFocusAreaSupported(mParameters);
+ mMeteringAreaSupported = CameraUtil.isMeteringAreaSupported(mParameters);
+ mAeLockSupported = CameraUtil.isAutoExposureLockSupported(mParameters);
+ mAwbLockSupported = CameraUtil.isAutoWhiteBalanceLockSupported(mParameters);
+ }
+
// Preview texture has been copied. Now camera can be released and the
// animation can be started.
@Override
@@ -3012,8 +3244,7 @@ public class VideoModule implements CameraModule,
return;
}
forceFlashOffIfSupported(forceOff);
- mCameraDevice.setParameters(mCameraDevice.getParameters());
- mUI.updateOnScreenIndicators(mParameters, mPreferences);
+ mCameraDevice.setParameters(mParameters);
}
@Override
@@ -3175,9 +3406,9 @@ public class VideoModule implements CameraModule,
|| mFaceDetectionStarted) return;
if (mParameters.getMaxNumDetectedFaces() > 0) {
mFaceDetectionStarted = true;
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+ CameraHolder.CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
mUI.onStartFaceDetection(mCameraDisplayOrientation,
- (info.facing == CameraInfo.CAMERA_FACING_FRONT));
+ (info.facing == CameraHolder.CameraInfo.CAMERA_FACING_FRONT));
mCameraDevice.setFaceDetectionCallback(mHandler, mUI);
Log.d(TAG, "start face detection Video "+mParameters.getMaxNumDetectedFaces());
mCameraDevice.startFaceDetection();
@@ -3190,7 +3421,6 @@ public class VideoModule implements CameraModule,
if (mParameters.getMaxNumDetectedFaces() > 0) {
mFaceDetectionStarted = false;
mCameraDevice.setFaceDetectionCallback(null, null);
- mUI.pauseFaceDetection();
mCameraDevice.stopFaceDetection();
mUI.onStopFaceDetection();
}
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index 3a21a060a..beb623e50 100755
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -44,6 +44,7 @@ import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;
+import android.view.View.OnLayoutChangeListener;
import com.android.camera.CameraManager.CameraProxy;
import com.android.camera.CameraPreference.OnPreferenceChangedListener;
@@ -60,6 +61,7 @@ import com.android.camera.ui.RotateImageView;
import com.android.camera.ui.RotateLayout;
import com.android.camera.ui.RotateTextToast;
import com.android.camera.ui.ZoomRenderer;
+import com.android.camera.ui.focus.FocusRing;
import com.android.camera.util.CameraUtil;
public class VideoUI implements PieRenderer.PieListener,
@@ -70,6 +72,7 @@ public class VideoUI implements PieRenderer.PieListener,
CameraManager.CameraFaceDetectionCallback{
private static final String TAG = "CAM_VideoUI";
// module fields
+ private final FocusRing mFocusRing;
private CameraActivity mActivity;
private View mRootView;
private SurfaceHolder mSurfaceHolder;
@@ -93,7 +96,6 @@ public class VideoUI implements PieRenderer.PieListener,
private ZoomRenderer mZoomRenderer;
private PreviewGestures mGestures;
private View mMenuButton;
- private OnScreenIndicators mOnScreenIndicators;
private RotateLayout mRecordingTimeRect;
private boolean mRecordingStarted = false;
private VideoController mController;
@@ -243,6 +245,7 @@ public class VideoUI implements PieRenderer.PieListener,
}
});
+ mFocusRing = (FocusRing) mRootView.findViewById(R.id.focus_ring);
mFlashOverlay = mRootView.findViewById(R.id.flash_overlay);
mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
mSwitcher = (ModuleSwitcher) mRootView.findViewById(R.id.camera_switcher);
@@ -276,8 +279,8 @@ public class VideoUI implements PieRenderer.PieListener,
});
initializeMiscControls();
- initializeControlByIntent();
initializeOverlay();
+ initializeControlByIntent();
initializePauseButton();
mCameraControls = (CameraControls) mRootView.findViewById(R.id.camera_controls);
@@ -293,7 +296,7 @@ public class VideoUI implements PieRenderer.PieListener,
mPrevOrientationResize = false;
Point size = new Point();
- mActivity.getWindowManager().getDefaultDisplay().getSize(size);
+ mActivity.getWindowManager().getDefaultDisplay().getRealSize(size);
mScreenRatio = CameraUtil.determineRatio(size.x, size.y);
calculateMargins(size);
mCameraControls.setMargins(mTopMargin, mBottomMargin);
@@ -336,9 +339,6 @@ public class VideoUI implements PieRenderer.PieListener,
});
mCameraControls = (CameraControls) mRootView.findViewById(R.id.camera_controls);
- mOnScreenIndicators = new OnScreenIndicators(mActivity,
- mRootView.findViewById(R.id.on_screen_indicators));
- mOnScreenIndicators.resetToDefault();
if (mController.isVideoCaptureIntent()) {
hideSwitcher();
mActivity.getLayoutInflater().inflate(R.layout.review_module_control,
@@ -382,9 +382,7 @@ public class VideoUI implements PieRenderer.PieListener,
} else {
ratio = (float) height / width;
}
- if (mOrientationResize &&
- mActivity.getResources().getConfiguration().orientation
- != Configuration.ORIENTATION_PORTRAIT) {
+ if (mOrientationResize && CameraUtil.isScreenRotated(mActivity)) {
ratio = 1 / ratio;
}
@@ -400,8 +398,11 @@ public class VideoUI implements PieRenderer.PieListener,
private void layoutPreview(float ratio) {
FrameLayout.LayoutParams lp = null;
- float scaledTextureWidth, scaledTextureHeight;
+ float scaledTextureWidth = 0.0f, scaledTextureHeight = 0.0f;
int rotation = CameraUtil.getDisplayRotation(mActivity);
+ if (!CameraUtil.isDefaultToPortrait(mActivity)) {
+ rotation = (rotation - 90) % 360;
+ }
mScreenRatio = CameraUtil.determineRatio(ratio);
if (mScreenRatio == CameraUtil.RATIO_16_9
&& CameraUtil.determinCloseRatio(ratio) == CameraUtil.RATIO_4_3) {
@@ -503,6 +504,10 @@ public class VideoUI implements PieRenderer.PieListener,
}
+ if (scaledTextureWidth > 0 && scaledTextureHeight > 0) {
+ mController.onScreenSizeChanged((int) scaledTextureWidth,
+ (int) scaledTextureHeight);
+ }
}
/**
@@ -719,17 +724,8 @@ public class VideoUI implements PieRenderer.PieListener,
mPauseButton.setOnPauseButtonListener(this);
}
- public void updateOnScreenIndicators(Parameters param, ComboPreferences prefs) {
- mOnScreenIndicators.updateFlashOnScreenIndicator(param.getFlashMode());
- boolean location = RecordLocationPreference.get(prefs, CameraSettings.KEY_RECORD_LOCATION);
- mOnScreenIndicators.updateLocationIndicator(location);
-
- }
-
public void setAspectRatio(double ratio) {
- if (mOrientationResize &&
- mActivity.getResources().getConfiguration().orientation
- != Configuration.ORIENTATION_PORTRAIT) {
+ if (mOrientationResize && CameraUtil.isScreenRotated(mActivity)) {
ratio = 1 / ratio;
}
@@ -896,9 +892,9 @@ public class VideoUI implements PieRenderer.PieListener,
mVideoMenu.animateSlideIn(mMenuLayout, CameraActivity.SETTING_LIST_WIDTH_1, true);
if (level == 2)
mVideoMenu.animateFadeIn(popup);
+ } else {
+ popup.setAlpha(1f);
}
- else
- popup.setAlpha(0.85f);
}
public ViewGroup getMenuLayout() {
@@ -982,7 +978,6 @@ public class VideoUI implements PieRenderer.PieListener,
public void showRecordingUI(boolean recording) {
mRecordingStarted = recording;
mMenuButton.setVisibility(recording ? View.GONE : View.VISIBLE);
- mOnScreenIndicators.setVisibility(recording ? View.GONE : View.VISIBLE);
if (recording) {
mShutterButton.setImageResource(R.drawable.shutter_button_video_stop);
hideSwitcher();
@@ -1022,7 +1017,6 @@ public class VideoUI implements PieRenderer.PieListener,
mMenuButton.setVisibility(View.GONE);
mCameraControls.hideUI();
mVideoMenu.hideUI();
- mOnScreenIndicators.setVisibility(View.GONE);
}
public void hideReviewUI() {
@@ -1031,20 +1025,11 @@ public class VideoUI implements PieRenderer.PieListener,
mMenuButton.setVisibility(View.VISIBLE);
mCameraControls.showUI();
mVideoMenu.showUI();
- mOnScreenIndicators.setVisibility(View.VISIBLE);
CameraUtil.fadeOut(mReviewDoneButton);
CameraUtil.fadeOut(mReviewPlayButton);
CameraUtil.fadeIn(mShutterButton);
}
- private void setShowMenu(boolean show) {
- if (mController.isVideoCaptureIntent())
- return;
- if (mOnScreenIndicators != null) {
- mOnScreenIndicators.setVisibility(show ? View.VISIBLE : View.GONE);
- }
- }
-
public void onPreviewFocusChanged(boolean previewFocused) {
if (previewFocused) {
showUI();
@@ -1058,7 +1043,6 @@ public class VideoUI implements PieRenderer.PieListener,
// this can not happen in capture mode
mRenderOverlay.setVisibility(previewFocused ? View.VISIBLE : View.GONE);
}
- setShowMenu(previewFocused);
}
public void initializePopup(PreferenceGroup pref) {
@@ -1105,6 +1089,13 @@ public class VideoUI implements PieRenderer.PieListener,
return mCameraControls.getVisibility() == View.VISIBLE;
}
+ public boolean onScaleStepResize(boolean direction) {
+ if (mGestures != null) {
+ return mGestures.onScaleStepResize(direction);
+ }
+ return false;
+ }
+
@Override
public void onDisplayChanged() {
mCameraControls.checkLayoutFlip();
@@ -1250,14 +1241,6 @@ public class VideoUI implements PieRenderer.PieListener,
mFaceView.setFaces(faces);
}
- public void pauseFaceDetection() {
- if (mFaceView != null) mFaceView.pause();
- }
-
- public void resumeFaceDetection() {
- if (mFaceView != null) mFaceView.resume();
- }
-
public void onStartFaceDetection(int orientation, boolean mirror) {
mFaceView.setBlockDraw(false);
mFaceView.clear();
@@ -1273,4 +1256,8 @@ public class VideoUI implements PieRenderer.PieListener,
mFaceView.clear();
}
}
+
+ public FocusRing getFocusRing() {
+ return mFocusRing;
+ }
}
diff --git a/src/com/android/camera/WideAnglePanoramaModule.java b/src/com/android/camera/WideAnglePanoramaModule.java
index 0aab8f804..364e815ff 100644
--- a/src/com/android/camera/WideAnglePanoramaModule.java
+++ b/src/com/android/camera/WideAnglePanoramaModule.java
@@ -16,7 +16,6 @@
package com.android.camera;
-import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -68,9 +67,10 @@ public class WideAnglePanoramaModule
implements CameraModule, WideAnglePanoramaController,
SurfaceTexture.OnFrameAvailableListener {
- public static final int DEFAULT_SWEEP_ANGLE = 160;
+ public static final int DEFAULT_SWEEP_ANGLE_PORTRAIT = 160;
+ public static final int DEFAULT_SWEEP_ANGLE_LANDSCAPE = 270;
public static final int DEFAULT_BLEND_MODE = Mosaic.BLENDTYPE_HORIZONTAL;
- public static final int DEFAULT_CAPTURE_PIXELS = 960 * 720;
+ public static final int DEFAULT_CAPTURE_PIXELS = 1440 * 1000;
private static final int MSG_LOW_RES_FINAL_MOSAIC_READY = 1;
private static final int MSG_GENERATE_FINAL_MOSAIC_ERROR = 2;
@@ -124,15 +124,12 @@ public class WideAnglePanoramaModule
private float mHorizontalViewAngle;
private float mVerticalViewAngle;
- // Prefer FOCUS_MODE_INFINITY to FOCUS_MODE_CONTINUOUS_VIDEO because of
- // getting a better image quality by the former.
- private String mTargetFocusMode = Parameters.FOCUS_MODE_INFINITY;
-
private PanoOrientationEventListener mOrientationEventListener;
// The value could be 0, 90, 180, 270 for the 4 different orientations measured in clockwise
// respectively.
private int mDeviceOrientation;
private int mDeviceOrientationAtCapture;
+ private int mOrientationOffset;
private int mCameraOrientation;
private int mOrientationCompensation;
private boolean mOrientationLocked;
@@ -197,6 +194,7 @@ public class WideAnglePanoramaModule
// the camera then point the camera to floor or sky, we still have
// the correct orientation.
if (orientation == ORIENTATION_UNKNOWN) return;
+ orientation = (orientation - mOrientationOffset + 360) % 360;
int oldOrientation = mDeviceOrientation;
mDeviceOrientation = CameraUtil.roundOrientation(orientation, mDeviceOrientation);
// When the screen is unlocked, display rotation may change. Always
@@ -230,6 +228,7 @@ public class WideAnglePanoramaModule
public void init(CameraActivity activity, View parent) {
mActivity = activity;
mRootView = parent;
+ mOrientationOffset = CameraUtil.isDefaultToPortrait(mActivity) ? 0 : 90;
mOrientationManager = new OrientationManager(activity);
mCaptureState = CAPTURE_STATE_VIEWFINDER;
@@ -310,6 +309,9 @@ public class WideAnglePanoramaModule
CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal(), activity);
mLocationManager = new LocationManager(mActivity, null);
+ // Power shutter
+ mActivity.initPowerShutter(mPreferences);
+
mMainHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -427,7 +429,7 @@ public class WideAnglePanoramaModule
int w = size.width;
// we only want 4:3 format.
int d = DEFAULT_CAPTURE_PIXELS - h * w;
- if (needSmaller && d < 0) { // no bigger preview than 960x720.
+ if (needSmaller && d < 0) {
continue;
}
if (need4To3 && (h * 4 != w * 3)) {
@@ -456,6 +458,7 @@ public class WideAnglePanoramaModule
Log.d(TAG, "camera preview h = "
+ mCameraPreviewHeight + " , w = " + mCameraPreviewWidth);
parameters.setPreviewSize(mCameraPreviewWidth, mCameraPreviewHeight);
+ mUI.setPreviewSize(mCameraPreviewWidth, mCameraPreviewHeight);
List<int[]> frameRates = parameters.getSupportedPreviewFpsRange();
int last = frameRates.size() - 1;
@@ -464,12 +467,13 @@ public class WideAnglePanoramaModule
parameters.setPreviewFpsRange(minFps, maxFps);
Log.d(TAG, "preview fps: " + minFps + ", " + maxFps);
+ // use CAF for viewfinder until starting the real mosaic, then lock
List<String> supportedFocusModes = parameters.getSupportedFocusModes();
- if (supportedFocusModes.indexOf(mTargetFocusMode) >= 0) {
- parameters.setFocusMode(mTargetFocusMode);
+ if (supportedFocusModes.indexOf(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) >= 0) {
+ parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else {
// Use the default focus mode and log a message
- Log.w(TAG, "Cannot set the focus mode to " + mTargetFocusMode +
+ Log.w(TAG, "Cannot set the focus mode to " + Parameters.FOCUS_MODE_CONTINUOUS_PICTURE +
" becuase the mode is not supported.");
}
@@ -567,15 +571,28 @@ public class WideAnglePanoramaModule
public void startCapture() {
// Reset values so we can do this again.
+
+ Parameters parameters = mCameraDevice.getParameters();
+ List<String> supportedFocusModes = parameters.getSupportedFocusModes();
+ if (supportedFocusModes.indexOf(Parameters.FOCUS_MODE_FIXED) >= 0) {
+ parameters.setFocusMode(Parameters.FOCUS_MODE_FIXED);
+ } else {
+ // Use the default focus mode and log a message
+ Log.w(TAG, "Cannot set the focus mode to " + Parameters.FOCUS_MODE_FIXED +
+ " becuase the mode is not supported.");
+ }
+ parameters.setAutoExposureLock(true);
+ parameters.setAutoWhiteBalanceLock(true);
+ configureCamera(parameters);
+
mCancelComputation = false;
mTimeTaken = System.currentTimeMillis();
mActivity.setSwipingEnabled(false);
mCaptureState = CAPTURE_STATE_MOSAIC;
mUI.onStartCapture();
- Parameters parameters = mCameraDevice.getParameters();
- parameters.setAutoExposureLock(true);
- parameters.setAutoWhiteBalanceLock(true);
- configureCamera(parameters);
+
+ final int sweepAngle = (mDeviceOrientation == 90 || mDeviceOrientation == 270) ?
+ DEFAULT_SWEEP_ANGLE_LANDSCAPE : DEFAULT_SWEEP_ANGLE_PORTRAIT;
mMosaicFrameProcessor.setProgressListener(new MosaicFrameProcessor.ProgressListener() {
@Override
@@ -585,8 +602,8 @@ public class WideAnglePanoramaModule
float accumulatedVerticalAngle = progressY * mVerticalViewAngle;
boolean isRotated = !(mDeviceOrientationAtCapture == mDeviceOrientation);
if (isFinished
- || (Math.abs(accumulatedHorizontalAngle) >= DEFAULT_SWEEP_ANGLE)
- || (Math.abs(accumulatedVerticalAngle) >= DEFAULT_SWEEP_ANGLE)
+ || (Math.abs(accumulatedHorizontalAngle) >= sweepAngle)
+ || (Math.abs(accumulatedVerticalAngle) >= sweepAngle)
|| isRotated) {
stopCapture(false);
} else {
@@ -606,7 +623,7 @@ public class WideAnglePanoramaModule
mUI.resetCaptureProgress();
// TODO: calculate the indicator width according to different devices to reflect the actual
// angle of view of the camera device.
- mUI.setMaxCaptureProgress(DEFAULT_SWEEP_ANGLE);
+ mUI.setMaxCaptureProgress(sweepAngle);
mUI.showCaptureProgress();
mDeviceOrientationAtCapture = mDeviceOrientation;
keepScreenOn();
@@ -624,6 +641,14 @@ public class WideAnglePanoramaModule
Parameters parameters = mCameraDevice.getParameters();
parameters.setAutoExposureLock(false);
parameters.setAutoWhiteBalanceLock(false);
+ List<String> supportedFocusModes = parameters.getSupportedFocusModes();
+ if (supportedFocusModes.indexOf(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) >= 0) {
+ parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
+ } else {
+ // Use the default focus mode and log a message
+ Log.w(TAG, "Cannot set the focus mode to " + Parameters.FOCUS_MODE_CONTINUOUS_PICTURE +
+ " becuase the mode is not supported.");
+ }
configureCamera(parameters);
mMosaicFrameProcessor.setProgressListener(null);
@@ -701,13 +726,21 @@ public class WideAnglePanoramaModule
} catch (InterruptedException e) {
throw new RuntimeException("Panorama reportProgress failed", e);
}
- // Update the progress bar
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mUI.updateSavingProgress(progress);
- }
- });
+ // Update the progress bar if we haven't paused. In the case where
+ // we pause the UI, then launch the camera from the lockscreen with
+ // this thread still running, a new WideAnglePanoramaModule is
+ // created, but this thread is left running to finish the task (and
+ // mPaused continues to be true for that instance.
+ if (!mPaused) {
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (!mPaused) {
+ mUI.updateSavingProgress(progress);
+ }
+ }
+ });
+ }
}
}
};
@@ -725,9 +758,11 @@ public class WideAnglePanoramaModule
if (mUsingFrontCamera) {
// mCameraOrientation is negative with respect to the front facing camera.
// See document of android.hardware.Camera.Parameters.setRotation.
- orientation = (mDeviceOrientationAtCapture - mCameraOrientation - 360) % 360;
+ orientation = (mDeviceOrientationAtCapture - mCameraOrientation -
+ mOrientationOffset + 360) % 360;
} else {
- orientation = (mDeviceOrientationAtCapture + mCameraOrientation) % 360;
+ orientation = (mDeviceOrientationAtCapture + mCameraOrientation +
+ mOrientationOffset) % 360;
}
return orientation;
}
@@ -882,12 +917,7 @@ public class WideAnglePanoramaModule
return;
}
- int perct = 100;
- final ActivityManager am = (ActivityManager)
- mActivity.getSystemService(Context.ACTIVITY_SERVICE);
- if (am.isLowRamDevice()) {
- perct = mActivity.getResources().getInteger(R.integer.panorama_frame_size_reduction);
- }
+ int perct = mActivity.getResources().getInteger(R.integer.panorama_frame_size_reduction);
int width = (mCameraPreviewWidth * perct) / 100;
int height = (mCameraPreviewHeight * perct) / 100;
@@ -943,6 +973,10 @@ public class WideAnglePanoramaModule
}
mUI.showPreviewCover();
releaseCamera();
+
+ // Load the power shutter
+ mActivity.initPowerShutter(mPreferences);
+
synchronized (mRendererLock) {
mCameraTexture = null;
@@ -1139,6 +1173,13 @@ public class WideAnglePanoramaModule
mCameraTexture.setOnFrameAvailableListener(this);
mCameraDevice.setPreviewTexture(mCameraTexture);
}
+ mCameraDevice.setOneShotPreviewCallback(mMainHandler,
+ new CameraManager.CameraPreviewDataCallback() {
+ @Override
+ public void onPreviewFrame(byte[] data, CameraProxy camera) {
+ mUI.hidePreviewCover();
+ }
+ });
mCameraDevice.startPreview();
mCameraState = PREVIEW_ACTIVE;
}
@@ -1216,7 +1257,7 @@ public class WideAnglePanoramaModule
@Override
public void cancelHighResStitching() {
- if (mPaused || mCameraTexture == null) return;
+ if (mPaused) return;
cancelHighResComputation();
}
@@ -1235,14 +1276,51 @@ public class WideAnglePanoramaModule
public void onActivityResult(int requestCode, int resultCode, Intent data) {
}
-
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
+ // Do not handle any key if the activity is paused
+ // or not in active camera/video mode
+ if (mPaused) {
+ return true;
+ } else if (!mActivity.isInCameraApp()) {
+ return false;
+ }
+
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_MEDIA_NEXT:
+ case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+ return true;
+ case KeyEvent.KEYCODE_CAMERA:
+ case KeyEvent.KEYCODE_HEADSETHOOK:
+ if (event.getRepeatCount() == 0) {
+ onShutterButtonClick();
+ }
+ return true;
+ case KeyEvent.KEYCODE_POWER:
+ return true;
+ }
return false;
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_MEDIA_NEXT:
+ case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+ if (!CameraActivity.mPowerShutter && !CameraUtil.hasCameraKey()) {
+ onShutterButtonClick();
+ }
+ return true;
+ case KeyEvent.KEYCODE_POWER:
+ if (CameraActivity.mPowerShutter && !CameraUtil.hasCameraKey()) {
+ onShutterButtonClick();
+ }
+ return true;
+ }
return false;
}
diff --git a/src/com/android/camera/WideAnglePanoramaUI.java b/src/com/android/camera/WideAnglePanoramaUI.java
index 46cf173bb..523abe411 100644
--- a/src/com/android/camera/WideAnglePanoramaUI.java
+++ b/src/com/android/camera/WideAnglePanoramaUI.java
@@ -99,7 +99,6 @@ public class WideAnglePanoramaUI implements
// Color definitions.
private int mIndicatorColor;
private int mIndicatorColorFast;
- private int mReviewBackground;
private SurfaceTexture mSurfaceTexture;
private View mPreviewCover;
@@ -109,6 +108,10 @@ public class WideAnglePanoramaUI implements
private RotateLayout mPanoFailedDialog;
private Button mPanoFailedButton;
+ private int mTopMargin = 0;
+ private int mBottomMargin = 0;
+ private float mAspectRatio = 1.0f;
+
/** Constructor. */
public WideAnglePanoramaUI(
CameraActivity activity,
@@ -145,6 +148,14 @@ public class WideAnglePanoramaUI implements
muteButton.setVisibility(View.GONE);
}
+ private void calculateMargins(Point size) {
+ int l = size.x > size.y ? size.x : size.y;
+ int tm = mActivity.getResources().getDimensionPixelSize(R.dimen.preview_top_margin);
+ int bm = mActivity.getResources().getDimensionPixelSize(R.dimen.preview_bottom_margin);
+ mTopMargin = l / 4 * tm / (tm + bm);
+ mBottomMargin = l / 4 - mTopMargin;
+ }
+
public void onStartCapture() {
hideSwitcher();
mShutterButton.setImageResource(R.drawable.shutter_button_stop);
@@ -364,32 +375,27 @@ public class WideAnglePanoramaUI implements
Display display = mActivity.getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
+ mActivity.getWindowManager().getDefaultDisplay().getRealSize(size);
+ calculateMargins(size);
+ mCameraControls.setMargins(mTopMargin, mBottomMargin);
int width = size.x;
- int height = size.y;
+ int height = size.y - mTopMargin - mBottomMargin;
int xOffset = 0;
int yOffset = 0;
int w = width;
int h = height;
h = w * 4 / 3;
- yOffset = (height - h) / 2;
+ yOffset = (height - h) / 2 + mTopMargin;
FrameLayout.LayoutParams param = new FrameLayout.LayoutParams(w, h);
mTextureView.setLayoutParams(param);
mTextureView.setX(xOffset);
mTextureView.setY(yOffset);
- mPreviewBorder.setLayoutParams(param);
- mPreviewBorder.setX(xOffset);
- mPreviewBorder.setY(yOffset);
mPreviewYOffset = yOffset;
- int t = mPreviewYOffset;
- int b1 = mTextureView.getBottom() - mPreviewYOffset;
- int r = mTextureView.getRight();
- int b2 = mTextureView.getBottom();
-
- mCameraControls.setPreviewRatio(1.0f, true);
+ mTextureView.layout(0, mPreviewYOffset, mTextureView.getRight(), mTextureView.getBottom());
}
public void resetSavingProgress() {
@@ -442,7 +448,6 @@ public class WideAnglePanoramaUI implements
Resources appRes = mActivity.getResources();
mIndicatorColor = appRes.getColor(R.color.pano_progress_indication);
- mReviewBackground = appRes.getColor(R.color.review_background);
mIndicatorColorFast = appRes.getColor(R.color.pano_progress_indication_fast);
mPreviewCover = mRootView.findViewById(R.id.preview_cover);
@@ -469,10 +474,8 @@ public class WideAnglePanoramaUI implements
mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
mShutterButton.setImageResource(R.drawable.btn_new_shutter);
mShutterButton.setOnShutterButtonListener(this);
- // Hide menu and indicators.
+ // Hide menu
mRootView.findViewById(R.id.menu).setVisibility(View.GONE);
- mRootView.findViewById(R.id.on_screen_indicators).setVisibility(View.GONE);
- mReview.setBackgroundColor(mReviewBackground);
// TODO: set display change listener properly.
((CameraRootView) mRootView).setDisplayChangeListener(null);
@@ -705,7 +708,34 @@ public class WideAnglePanoramaUI implements
mPanoFailedDialog.setRotation(-orientation);
mReview.setRotation(-orientation);
mTooFastPrompt.setRotation(-orientation);
+ mPreviewBorder.setRotation(-orientation);
mCameraControls.setOrientation(orientation, animation);
RotateTextToast.setOrientation(orientation);
}
+
+ public void hidePreviewCover() {
+ // Hide the preview cover if need.
+ if (mPreviewCover.getVisibility() != View.GONE) {
+ mPreviewCover.setVisibility(View.GONE);
+ }
+ }
+
+ public void setPreviewSize(int width, int height) {
+ if (width == 0 || height == 0) {
+ Log.w(TAG, "Preview size should not be 0.");
+ return;
+ }
+ float ratio;
+ if (width > height) {
+ ratio = (float) width / height;
+ } else {
+ ratio = (float) height / width;
+ }
+
+ if (ratio != mAspectRatio) {
+ mAspectRatio = ratio;
+ }
+
+ mCameraControls.setPreviewRatio(mAspectRatio, false);
+ }
}
diff --git a/src/com/android/camera/app/CameraApp.java b/src/com/android/camera/app/CameraApp.java
index 837e22cd1..dc5825cb1 100644
--- a/src/com/android/camera/app/CameraApp.java
+++ b/src/com/android/camera/app/CameraApp.java
@@ -18,6 +18,7 @@ package com.android.camera.app;
import android.app.ActivityManager;
import android.app.Application;
+import android.content.Context;
import com.android.camera.SDCard;
import com.android.camera.util.CameraUtil;
@@ -28,9 +29,12 @@ public class CameraApp extends Application {
private static long mMaxSystemMemory;
public static boolean mIsLowMemoryDevice = false;
private static final long LOW_MEMORY_DEVICE_THRESHOLD = 2L*1024*1024*1024;
+ private static Application mApp = null;
+
@Override
public void onCreate() {
super.onCreate();
+ mApp = this;
ActivityManager actManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
actManager.getMemoryInfo(memInfo);
@@ -43,5 +47,9 @@ public class CameraApp extends Application {
CameraUtil.initialize(this);
SDCard.initialize(this);
}
+
+ public static Context getContext() {
+ return mApp.getApplicationContext();
+ }
}
diff --git a/src/com/android/camera/async/HandlerExecutor.java b/src/com/android/camera/async/HandlerExecutor.java
new file mode 100644
index 000000000..87c8c0ce0
--- /dev/null
+++ b/src/com/android/camera/async/HandlerExecutor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.async;
+
+import java.util.concurrent.Executor;
+
+import android.os.Handler;
+
+/**
+ * An {@link Executor} which posts to a {@link Handler}.
+ */
+public class HandlerExecutor implements Executor {
+ private final Handler mHandler;
+
+ public HandlerExecutor(Handler handler) {
+ mHandler = handler;
+ }
+
+ @Override
+ public void execute(Runnable runnable) {
+ mHandler.post(runnable);
+ }
+}
diff --git a/src/com/android/camera/async/MainThread.java b/src/com/android/camera/async/MainThread.java
new file mode 100644
index 000000000..7fdb3ec9b
--- /dev/null
+++ b/src/com/android/camera/async/MainThread.java
@@ -0,0 +1,47 @@
+/*
+ * 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.async;
+
+import android.os.Handler;
+import android.os.Looper;
+
+public class MainThread extends HandlerExecutor {
+ private MainThread(Handler handler) {
+ super(handler);
+ }
+
+ public static MainThread create() {
+ return new MainThread(new Handler(Looper.getMainLooper()));
+ }
+
+ /**
+ * Caches whether or not the current thread is the main thread.
+ */
+ private static final ThreadLocal<Boolean> sIsMainThread = new ThreadLocal<Boolean>() {
+ @Override
+ protected Boolean initialValue() {
+ return Looper.getMainLooper().getThread() == Thread.currentThread();
+ }
+ };
+
+ /**
+ * Returns true if the method is run on the main android thread.
+ */
+ public static boolean isMainThread() {
+ return sIsMainThread.get();
+ }
+}
diff --git a/src/com/android/camera/crop/CropActivity.java b/src/com/android/camera/crop/CropActivity.java
index 9c09b9a87..45455ccad 100644
--- a/src/com/android/camera/crop/CropActivity.java
+++ b/src/com/android/camera/crop/CropActivity.java
@@ -31,6 +31,7 @@ import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -46,6 +47,7 @@ import org.codeaurora.snapcam.R;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
@@ -581,6 +583,16 @@ public class CropActivity extends Activity {
}
}
}
+
+ File dest = SaveImage.getLocalFileFromUri(CropActivity.this, mOutUri);
+ if (dest != null) {
+ MediaScannerConnection.scanFile(
+ CropActivity.this,
+ new String[] { dest.toString() },
+ null /* no mimetype, let scanner guess */,
+ null /* no callback */);
+ }
+
return !failure; // True if any of the operations failed
}
@@ -590,7 +602,6 @@ public class CropActivity extends Activity {
Utils.closeSilently(mInStream);
doneBitmapIO(result.booleanValue(), mResultIntent);
}
-
}
private void done() {
diff --git a/src/com/android/camera/crop/SaveImage.java b/src/com/android/camera/crop/SaveImage.java
index c48e861fe..1701fb6eb 100644
--- a/src/com/android/camera/crop/SaveImage.java
+++ b/src/com/android/camera/crop/SaveImage.java
@@ -142,16 +142,19 @@ public class SaveImage {
return saveDirectory;
}
- public static File getNewFile(Context context, Uri sourceUri) {
+ public static File getNewFile(Context context, Uri sourceUri, long time) {
File saveDirectory = getFinalSaveDirectory(context, sourceUri);
- String filename = new SimpleDateFormat(TIME_STAMP_NAME).format(new Date(
- System.currentTimeMillis()));
+ String filename = new SimpleDateFormat(TIME_STAMP_NAME).format(new Date(time));
if (hasPanoPrefix(context, sourceUri)) {
return new File(saveDirectory, PREFIX_PANO + filename + POSTFIX_JPG);
}
return new File(saveDirectory, PREFIX_IMG + filename + POSTFIX_JPG);
}
+ public static File getNewFile(Context context, Uri sourceUri) {
+ return getNewFile(context, sourceUri, System.currentTimeMillis());
+ }
+
/**
* Remove the files in the auxiliary directory whose names are the same as
* the source image.
@@ -339,9 +342,7 @@ public class SaveImage {
public static Uri makeAndInsertUri(Context context, Uri sourceUri) {
long time = System.currentTimeMillis();
- String filename = new SimpleDateFormat(TIME_STAMP_NAME).format(new Date(time));
- File saveDirectory = getFinalSaveDirectory(context, sourceUri);
- File file = new File(saveDirectory, filename + ".JPG");
+ File file = getNewFile(context, sourceUri, time);
return linkNewFileToUri(context, sourceUri, file, time, false);
}
@@ -384,7 +385,7 @@ public class SaveImage {
* @return The file object. Return null if srcUri is invalid or not a local
* file.
*/
- private static File getLocalFileFromUri(Context context, Uri srcUri) {
+ static File getLocalFileFromUri(Context context, Uri srcUri) {
if (srcUri == null) {
Log.e(LOGTAG, "srcUri is null.");
return null;
diff --git a/src/com/android/camera/data/AbstractLocalDataAdapterWrapper.java b/src/com/android/camera/data/AbstractLocalDataAdapterWrapper.java
index ef1e4258c..bc239788b 100644
--- a/src/com/android/camera/data/AbstractLocalDataAdapterWrapper.java
+++ b/src/com/android/camera/data/AbstractLocalDataAdapterWrapper.java
@@ -98,4 +98,9 @@ public abstract class AbstractLocalDataAdapterWrapper implements LocalDataAdapte
public void refresh(ContentResolver resolver, Uri uri) {
mAdapter.refresh(resolver, uri);
}
+
+ @Override
+ public void stopLoading() {
+ mAdapter.stopLoading();
+ }
}
diff --git a/src/com/android/camera/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java
index 4b810a0fa..95c1ea723 100755
--- a/src/com/android/camera/data/CameraDataAdapter.java
+++ b/src/com/android/camera/data/CameraDataAdapter.java
@@ -52,6 +52,7 @@ public class CameraDataAdapter implements LocalDataAdapter {
private int mSuggestedHeight = DEFAULT_DECODE_SIZE;
private LocalData mLocalDataToDelete;
+ private QueryTask mQueryTask;
public CameraDataAdapter(Drawable placeHolder) {
mImages = new LocalDataList();
@@ -60,8 +61,15 @@ public class CameraDataAdapter implements LocalDataAdapter {
@Override
public void requestLoad(ContentResolver resolver) {
- QueryTask qtask = new QueryTask();
- qtask.execute(resolver);
+ mQueryTask = new QueryTask();
+ mQueryTask.execute(resolver);
+ }
+
+ @Override
+ public void stopLoading() {
+ if (mQueryTask != null) {
+ mQueryTask.cancel(true);
+ }
}
@Override
@@ -329,7 +337,7 @@ public class CameraDataAdapter implements LocalDataAdapter {
if (c != null && c.moveToFirst()) {
// build up the list.
c.moveToFirst();
- while (true) {
+ while (!isCancelled()) {
LocalData data = LocalMediaData.VideoData.buildFromCursor(c);
if (data != null) {
l.add(data);
@@ -357,7 +365,12 @@ public class CameraDataAdapter implements LocalDataAdapter {
@Override
protected void onPostExecute(LocalDataList l) {
- replaceData(l);
+ if (!isCancelled()) {
+ replaceData(l);
+ }
+ if (mQueryTask == this) {
+ mQueryTask = null;
+ }
}
}
diff --git a/src/com/android/camera/data/LocalDataAdapter.java b/src/com/android/camera/data/LocalDataAdapter.java
index 0a5fde0b5..d8c5971ac 100644
--- a/src/com/android/camera/data/LocalDataAdapter.java
+++ b/src/com/android/camera/data/LocalDataAdapter.java
@@ -115,4 +115,7 @@ public interface LocalDataAdapter extends DataAdapter {
/** Insert a data. */
public void insertData(LocalData data);
+
+ /** Stop data loading */
+ public void stopLoading();
}
diff --git a/src/com/android/camera/exif/ExifInterface.java b/src/com/android/camera/exif/ExifInterface.java
index 4ecdd7703..82dee3a19 100644
--- a/src/com/android/camera/exif/ExifInterface.java
+++ b/src/com/android/camera/exif/ExifInterface.java
@@ -1097,7 +1097,16 @@ public class ExifInterface {
throws FileNotFoundException,
IOException {
// Attempt in-place write
- if (!rewriteExif(filename, tags)) {
+ boolean rewriteOkay = false;
+ try {
+ rewriteOkay = rewriteExif(filename, tags);
+ } catch (IOException e) {
+ // If jpeg does not contains exif, rewriteExif
+ // will throw EOF IOException, let's catch
+ // it and fall back to do a copy instead
+ // of in-place replacement.
+ }
+ if (!rewriteOkay) {
// Fall back to doing a copy
ExifData tempData = mData;
mData = new ExifData(DEFAULT_BYTE_ORDER);
diff --git a/src/com/android/camera/exif/ExifOutputStream.java b/src/com/android/camera/exif/ExifOutputStream.java
index 90d432769..47b95d80f 100644
--- a/src/com/android/camera/exif/ExifOutputStream.java
+++ b/src/com/android/camera/exif/ExifOutputStream.java
@@ -491,7 +491,7 @@ class ExifOutputStream extends FilterOutputStream {
switch (tag.getDataType()) {
case ExifTag.TYPE_ASCII:
byte buf[] = tag.getStringByte();
- if (buf.length == tag.getComponentCount()) {
+ if (buf.length == tag.getComponentCount() && buf.length > 0) {
buf[buf.length - 1] = 0;
dataOutputStream.write(buf);
} else {
diff --git a/src/com/android/camera/imageprocessor/PostProcessor.java b/src/com/android/camera/imageprocessor/PostProcessor.java
index c227f32b2..77040aa09 100755
--- a/src/com/android/camera/imageprocessor/PostProcessor.java
+++ b/src/com/android/camera/imageprocessor/PostProcessor.java
@@ -139,7 +139,7 @@ public class PostProcessor{
private CameraCaptureSession mCaptureSession;
private ImageReader mImageReader;
private ImageReader mZSLReprocessImageReader;
- private boolean mUseZSL = true;
+ private boolean mUseZSL = false;
private boolean mSaveRaw = false;
private Handler mZSLHandler;
private HandlerThread mZSLHandlerThread;
@@ -155,6 +155,14 @@ public class PostProcessor{
public int mMaxRequiredImageNum;
private boolean mIsDeepPortrait = false;
+ private void checkAndEnableZSL(int cameraId) {
+ if (mController.mSettingsManager.isZslSupported(cameraId)) {
+ mUseZSL = true;
+ } else {
+ mUseZSL = false;
+ }
+ }
+
public int getMaxRequiredImageNum() {
return mMaxRequiredImageNum;
}
@@ -633,6 +641,7 @@ public class PostProcessor{
public PostProcessor(CameraActivity activity, CaptureModule module) {
mController = module;
mActivity = activity;
+ checkAndEnableZSL(mController.getMainCameraId());
mNamedImages = new PhotoModule.NamedImages();
}
@@ -694,19 +703,23 @@ public class PostProcessor{
mImageHandlerTask = new ImageHandlerTask();
mSaveRaw = isSaveRaw;
mIsDeepPortrait = isDeepPortrait;
- if(setFilter(postFilterId) || isFlashModeOn || isTrackingFocusOn || isMakeupOn || isSelfieMirrorOn
- || PersistUtil.getCameraZSLDisabled()
- || !SettingsManager.getInstance().isZSLInAppEnabled()
- || "enable".equals(
- SettingsManager.getInstance().getValue(SettingsManager.KEY_AUTO_HDR))
- || SettingsManager.getInstance().isCamera2HDRSupport()
- || "18".equals(SettingsManager.getInstance().getValue(
- SettingsManager.KEY_SCENE_MODE))
- || mController.getCameraMode() == CaptureModule.DUAL_MODE
- || isSupportedQcfa || isDeepPortrait) {
- mUseZSL = false;
+ if (mController.mSettingsManager.isZslSupported(mController.getMainCameraId())) {
+ if (setFilter(postFilterId) || isFlashModeOn || isTrackingFocusOn || isMakeupOn
+ || isSelfieMirrorOn || PersistUtil.getCameraZSLDisabled()
+ || !SettingsManager.getInstance().isZSLInAppEnabled()
+ || "enable".equals(
+ SettingsManager.getInstance().getValue(SettingsManager.KEY_AUTO_HDR))
+ || SettingsManager.getInstance().isCamera2HDRSupport()
+ || "18".equals(
+ SettingsManager.getInstance().getValue(SettingsManager.KEY_SCENE_MODE))
+ || mController.getCameraMode() == CaptureModule.DUAL_MODE
+ || isSupportedQcfa || isDeepPortrait) {
+ mUseZSL = false;
+ } else {
+ mUseZSL = true;
+ }
} else {
- mUseZSL = true;
+ mUseZSL = false;
}
Log.d(TAG,"ZSL is "+mUseZSL);
startBackgroundThread();
@@ -1326,6 +1339,6 @@ public class PostProcessor{
private native int nativeResizeImage(byte[] oldBuf, byte[] newBuf, int oldWidth, int oldHeight, int oldStride, int newWidth, int newHeight);
private native int nativeFlipNV21(byte[] buf, int stride, int height, int gap, boolean isVertical);
static {
- System.loadLibrary("jni_imageutil");
+ System.loadLibrary("jni_snapimageutil");
}
}
diff --git a/src/com/android/camera/tinyplanet/TinyPlanetNative.java b/src/com/android/camera/tinyplanet/TinyPlanetNative.java
index 1d456de9e..8f320a960 100644
--- a/src/com/android/camera/tinyplanet/TinyPlanetNative.java
+++ b/src/com/android/camera/tinyplanet/TinyPlanetNative.java
@@ -23,7 +23,7 @@ import android.graphics.Bitmap;
*/
public class TinyPlanetNative {
static {
- System.loadLibrary("jni_snapcamtinyplanet");
+ System.loadLibrary("jni_snaptinyplanet");
}
/**
diff --git a/src/com/android/camera/ui/Arrows.java b/src/com/android/camera/ui/Arrows.java
deleted file mode 100644
index 4923eb10e..000000000
--- a/src/com/android/camera/ui/Arrows.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-Copyright (c) 2016, The Linux Foundation. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- * Neither the name of The Linux Foundation nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-package com.android.camera.ui;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.util.AttributeSet;
-import android.view.View;
-
-import java.util.ArrayList;
-
-public class Arrows extends View {
- private static final int ARROW_COLOR = Color.WHITE;
- private static final double ARROW_END_DEGREE = 15d;
- private static final int ARROW_END_LENGTH = 50;
-
- private Paint mPaint;
- private ArrayList<Path> mPaths;
-
- public Arrows(Context context, AttributeSet attrs) {
- super(context, attrs);
- mPaths = new ArrayList<Path>();
- mPaint = new Paint();
- mPaint.setStyle(Paint.Style.STROKE);
- mPaint.setColor(ARROW_COLOR);
- mPaint.setStrokeWidth(2f);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (mPaths != null) {
- for(int i=0; i < mPaths.size(); i++) {
- canvas.drawPath(mPaths.get(i), mPaint);
- }
- }
- }
-
- public void addPath(float[] x, float[] y) {
- Path path = new Path();
- path.reset();
- path.moveTo(x[0], y[0]);
- for(int i=1; i < x.length; i++) {
- if(i == x.length-1) {
- path.lineTo(x[i], y[i]);
-
- double setha = Math.toDegrees(Math.atan2(y[i] - y[i - 1], x[i] - x[i - 1]));
- setha = (setha + ARROW_END_DEGREE + 360) % 360;
- path.lineTo(x[i]-(float)(ARROW_END_LENGTH*Math.cos(Math.toRadians(setha))),
- y[i]-(float)(ARROW_END_LENGTH*Math.sin(Math.toRadians(setha))));
- path.lineTo(x[i], y[i]);
- setha = (setha - ARROW_END_DEGREE*2 + 360) % 360;
- path.lineTo(x[i]-(float)(ARROW_END_LENGTH*Math.cos(Math.toRadians(setha))),
- y[i]-(float)(ARROW_END_LENGTH*Math.sin(Math.toRadians(setha))));
- }
- else
- path.quadTo(x[i],y[i], x[i+1], y[i+1]);
- }
- mPaths.add(path);
- invalidate();
- }
-}
diff --git a/src/com/android/camera/ui/CameraControls.java b/src/com/android/camera/ui/CameraControls.java
index b85d7f1ca..26a405727 100644
--- a/src/com/android/camera/ui/CameraControls.java
+++ b/src/com/android/camera/ui/CameraControls.java
@@ -59,7 +59,6 @@ public class CameraControls extends RotatableLayout {
private View mFrontBackSwitcher;
private View mHdrSwitcher;
private View mTsMakeupSwitcher;
- private View mIndicators;
private View mPreview;
private View mSceneModeSwitcher;
private View mFilterModeSwitcher;
@@ -135,7 +134,6 @@ public class CameraControls extends RotatableLayout {
mMenu.setVisibility(View.INVISIBLE);
mMute.setVisibility(View.INVISIBLE);
mExitPanorama.setVisibility(View.INVISIBLE);
- mIndicators.setVisibility(View.INVISIBLE);
mPreview.setVisibility(View.INVISIBLE);
isAnimating = false;
enableTouch(true);
@@ -160,7 +158,6 @@ public class CameraControls extends RotatableLayout {
mMenu.setVisibility(View.INVISIBLE);
mMute.setVisibility(View.INVISIBLE);
mExitPanorama.setVisibility(View.INVISIBLE);
- mIndicators.setVisibility(View.INVISIBLE);
mPreview.setVisibility(View.INVISIBLE);
isAnimating = false;
enableTouch(true);
@@ -276,8 +273,6 @@ public class CameraControls extends RotatableLayout {
mViewList.add(mMute);
if (mExitPanorama.getVisibility() == View.VISIBLE)
mViewList.add(mExitPanorama);
- if (mIndicators.getVisibility() == View.VISIBLE)
- mViewList.add(mIndicators);
}
public void removeFromViewList(View view) {
@@ -303,7 +298,6 @@ public class CameraControls extends RotatableLayout {
mMute = findViewById(R.id.mute_button);
mExitPanorama = findViewById(R.id.exit_panorama);
mExitPanorama.setVisibility(View.GONE);
- mIndicators = findViewById(R.id.on_screen_indicators);
mPreview = findViewById(R.id.preview_thumb);
mSceneModeSwitcher = findViewById(R.id.scene_mode_switcher);
mFilterModeSwitcher = findViewById(R.id.filter_mode_switcher);
@@ -349,6 +343,7 @@ public class CameraControls extends RotatableLayout {
mReviewDoneButton = null;
}
layoutRemaingPhotos();
+ mRemainingPhotos.setVisibility(View.VISIBLE);
}
@Override
@@ -381,19 +376,18 @@ public class CameraControls extends RotatableLayout {
int rotation = getUnifiedRotation();
toIndex(mSwitcher, w, h, rotation, 4, 6, SWITCHER_INDEX);
toIndex(mVideoShutter, w, h, rotation, 3, 6, VIDEO_SHUTTER_INDEX);
- toIndex(mMenu, w, h, rotation, 4, 0, MENU_INDEX);
- toIndex(mMute, w, h, rotation, 3, 0, MUTE_INDEX);
+ toIndex(mSceneModeSwitcher, w, h, rotation, 4, 0, SCENE_MODE_INDEX);
+ toIndex(mMute, w, h, rotation, 4, 0, MUTE_INDEX);
+ toIndex(mFilterModeSwitcher, w, h, rotation, 3, 0, FILTER_MODE_INDEX);
toIndex(mExitPanorama, w, h, rotation, 0, 0, EXIT_PANORAMA_INDEX);
- toIndex(mIndicators, w, h, rotation, 0, 6, INDICATOR_INDEX);
- toIndex(mFrontBackSwitcher, w, h, rotation, 2, 0, FRONT_BACK_INDEX);
+ toIndex(mFrontBackSwitcher, w, h, rotation, 1, 0, FRONT_BACK_INDEX);
toIndex(mPreview, w, h, rotation, 0, 6, PREVIEW_INDEX);
if(TsMakeupManager.HAS_TS_MAKEUP) {
- toIndex(mTsMakeupSwitcher, w, h, rotation, 3, 0, TS_MAKEUP_INDEX);
+ toIndex(mTsMakeupSwitcher, w, h, rotation, 2, 0, TS_MAKEUP_INDEX);
} else {
- toIndex(mHdrSwitcher, w, h, rotation, 3, 0, HDR_INDEX);
+ toIndex(mHdrSwitcher, w, h, rotation, 2, 0, HDR_INDEX);
}
- toIndex(mFilterModeSwitcher, w, h, rotation, 1, 0, FILTER_MODE_INDEX);
- toIndex(mSceneModeSwitcher, w, h, rotation, 0, 0, SCENE_MODE_INDEX);
+ toIndex(mMenu, w, h, rotation, 0, 0, MENU_INDEX);
layoutToast(mRefocusToast, w, h, rotation);
}
@@ -498,7 +492,6 @@ public class CameraControls extends RotatableLayout {
mSwitcher.setX(mLocX[idx1][SWITCHER_INDEX] - x);
mShutter.setX(mLocX[idx1][SHUTTER_INDEX] - x);
mVideoShutter.setX(mLocX[idx1][VIDEO_SHUTTER_INDEX] - x);
- mIndicators.setX(mLocX[idx1][INDICATOR_INDEX] - x);
mPreview.setX(mLocX[idx1][PREVIEW_INDEX] - x);
mFrontBackSwitcher.setY(mLocY[idx1][FRONT_BACK_INDEX] + y);
@@ -515,7 +508,6 @@ public class CameraControls extends RotatableLayout {
mSwitcher.setY(mLocY[idx1][SWITCHER_INDEX] - y);
mShutter.setY(mLocY[idx1][SHUTTER_INDEX] - y);
mVideoShutter.setY(mLocY[idx1][VIDEO_SHUTTER_INDEX] - y);
- mIndicators.setY(mLocY[idx1][INDICATOR_INDEX] - y);
mPreview.setY(mLocY[idx1][PREVIEW_INDEX] - y);
}
@@ -550,7 +542,6 @@ public class CameraControls extends RotatableLayout {
mMenu.animate().cancel();
mMute.animate().cancel();
mExitPanorama.animate().cancel();
- mIndicators.animate().cancel();
mPreview.animate().cancel();
mFrontBackSwitcher.animate().setListener(outlistener);
((ModuleSwitcher) mSwitcher).removePopup();
@@ -573,7 +564,6 @@ public class CameraControls extends RotatableLayout {
mSwitcher.animate().translationYBy(mSize).setDuration(ANIME_DURATION);
mShutter.animate().translationYBy(mSize).setDuration(ANIME_DURATION);
mVideoShutter.animate().translationYBy(mSize).setDuration(ANIME_DURATION);
- mIndicators.animate().translationYBy(mSize).setDuration(ANIME_DURATION);
mPreview.animate().translationYBy(mSize).setDuration(ANIME_DURATION);
break;
case 90:
@@ -592,7 +582,6 @@ public class CameraControls extends RotatableLayout {
mSwitcher.animate().translationXBy(mSize).setDuration(ANIME_DURATION);
mShutter.animate().translationXBy(mSize).setDuration(ANIME_DURATION);
mVideoShutter.animate().translationXBy(mSize).setDuration(ANIME_DURATION);
- mIndicators.animate().translationXBy(mSize).setDuration(ANIME_DURATION);
mPreview.animate().translationXBy(mSize).setDuration(ANIME_DURATION);
break;
case 180:
@@ -611,7 +600,6 @@ public class CameraControls extends RotatableLayout {
mSwitcher.animate().translationYBy(-mSize).setDuration(ANIME_DURATION);
mShutter.animate().translationYBy(-mSize).setDuration(ANIME_DURATION);
mVideoShutter.animate().translationYBy(-mSize).setDuration(ANIME_DURATION);
- mIndicators.animate().translationYBy(-mSize).setDuration(ANIME_DURATION);
mPreview.animate().translationYBy(-mSize).setDuration(ANIME_DURATION);
break;
case 270:
@@ -630,7 +618,6 @@ public class CameraControls extends RotatableLayout {
mSwitcher.animate().translationXBy(-mSize).setDuration(ANIME_DURATION);
mShutter.animate().translationXBy(-mSize).setDuration(ANIME_DURATION);
mVideoShutter.animate().translationXBy(-mSize).setDuration(ANIME_DURATION);
- mIndicators.animate().translationXBy(-mSize).setDuration(ANIME_DURATION);
mPreview.animate().translationXBy(-mSize).setDuration(ANIME_DURATION);
break;
}
@@ -657,7 +644,6 @@ public class CameraControls extends RotatableLayout {
mMenu.animate().cancel();
mMute.animate().cancel();
mExitPanorama.animate().cancel();
- mIndicators.animate().cancel();
mPreview.animate().cancel();
if (mViewList != null)
for (View v : mViewList) {
@@ -669,7 +655,6 @@ public class CameraControls extends RotatableLayout {
shutterAnim.stop();
mMenu.setVisibility(View.VISIBLE);
- mIndicators.setVisibility(View.VISIBLE);
mPreview.setVisibility(View.VISIBLE);
mFrontBackSwitcher.animate().setListener(inlistener);
@@ -692,7 +677,6 @@ public class CameraControls extends RotatableLayout {
mSwitcher.animate().translationYBy(-mSize).setDuration(ANIME_DURATION);
mShutter.animate().translationYBy(-mSize).setDuration(ANIME_DURATION);
mVideoShutter.animate().translationYBy(-mSize).setDuration(ANIME_DURATION);
- mIndicators.animate().translationYBy(-mSize).setDuration(ANIME_DURATION);
mPreview.animate().translationYBy(-mSize).setDuration(ANIME_DURATION);
break;
case 90:
@@ -713,7 +697,6 @@ public class CameraControls extends RotatableLayout {
mSwitcher.animate().translationXBy(-mSize).setDuration(ANIME_DURATION);
mShutter.animate().translationXBy(-mSize).setDuration(ANIME_DURATION);
mVideoShutter.animate().translationXBy(-mSize).setDuration(ANIME_DURATION);
- mIndicators.animate().translationXBy(-mSize).setDuration(ANIME_DURATION);
mPreview.animate().translationXBy(-mSize).setDuration(ANIME_DURATION);
break;
case 180:
@@ -734,7 +717,6 @@ public class CameraControls extends RotatableLayout {
mSwitcher.animate().translationYBy(mSize).setDuration(ANIME_DURATION);
mShutter.animate().translationYBy(mSize).setDuration(ANIME_DURATION);
mVideoShutter.animate().translationYBy(mSize).setDuration(ANIME_DURATION);
- mIndicators.animate().translationYBy(mSize).setDuration(ANIME_DURATION);
mPreview.animate().translationYBy(mSize).setDuration(ANIME_DURATION);
break;
case 270:
@@ -755,7 +737,6 @@ public class CameraControls extends RotatableLayout {
mSwitcher.animate().translationXBy(mSize).setDuration(ANIME_DURATION);
mShutter.animate().translationXBy(mSize).setDuration(ANIME_DURATION);
mVideoShutter.animate().translationXBy(mSize).setDuration(ANIME_DURATION);
- mIndicators.animate().translationXBy(mSize).setDuration(ANIME_DURATION);
mPreview.animate().translationXBy(mSize).setDuration(ANIME_DURATION);
break;
}
@@ -1010,7 +991,7 @@ public class CameraControls extends RotatableLayout {
mPaint.setColor(getResources().getColor(R.color.camera_control_bg_transparent));
}
}
- invalidate();
+ requestLayout();
}
public void showRefocusToast(boolean show) {
@@ -1025,7 +1006,7 @@ public class CameraControls extends RotatableLayout {
View[] views = {
mSceneModeSwitcher, mFilterModeSwitcher, mFrontBackSwitcher,
TsMakeupManager.HAS_TS_MAKEUP ? mTsMakeupSwitcher : mHdrSwitcher,
- mMenu, mShutter, mPreview, mSwitcher, mMute, mReviewRetakeButton,
+ mMenu, mPreview, mSwitcher, mMute, mReviewRetakeButton,
mReviewCancelButton, mReviewDoneButton, mExitPanorama
};
for (View v : views) {
diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java
index e6e00ad56..6a767862f 100644
--- a/src/com/android/camera/ui/FilmStripView.java
+++ b/src/com/android/camera/ui/FilmStripView.java
@@ -2825,8 +2825,6 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
@Override
public boolean onScroll(float x, float y, float dx, float dy) {
- if (mPreviewGestures != null && mPreviewGestures.waitUntilNextDown())
- return false;
ViewItem currItem = mViewItem[mCurrentItem];
if (currItem == null) {
return false;
@@ -2892,8 +2890,6 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
@Override
public boolean onFling(float velocityX, float velocityY) {
- if (mPreviewGestures != null && mPreviewGestures.waitUntilNextDown())
- return false;
final ViewItem currItem = mViewItem[mCurrentItem];
if (currItem == null) {
return false;
diff --git a/src/com/android/camera/ui/ListMenu.java b/src/com/android/camera/ui/ListMenu.java
index d83114cce..88ad8fe2f 100644
--- a/src/com/android/camera/ui/ListMenu.java
+++ b/src/com/android/camera/ui/ListMenu.java
@@ -120,8 +120,7 @@ public class ListMenu extends ListView
+ " position " + position);
}
if (position == mHighlighted)
- view.setBackgroundColor(getContext().getResources()
- .getColor(R.color.setting_color));
+ view.setActivated(true);
return view;
}
@@ -160,7 +159,6 @@ public class ListMenu extends ListView
ArrayAdapter<ListPreference> mListItemAdapter = new MoreSettingAdapter();
setAdapter(mListItemAdapter);
setOnItemClickListener(this);
- setSelector(android.R.color.transparent);
// Initialize mEnabled
mEnabled = new boolean[mListItem.size()];
for (int i = 0; i < mEnabled.length; i++) {
@@ -183,7 +181,6 @@ public class ListMenu extends ListView
ArrayAdapter<ListPreference> mListItemAdapter = new MoreSettingAdapter();
setAdapter(mListItemAdapter);
setOnItemClickListener(this);
- setSelector(android.R.color.transparent);
// Initialize mEnabled
mEnabled = new boolean[mListItem.size()];
for (int i = 0; i < mEnabled.length; i++) {
@@ -229,7 +226,7 @@ public class ListMenu extends ListView
mEnabled[j] = enable;
int offset = getFirstVisiblePosition();
if (offset >= 0) {
- int indexInView = j - offset;
+ int indexInView = j + getHeaderViewsCount() - offset;
if (getChildCount() > indexInView && indexInView >= 0) {
getChildAt(indexInView).setEnabled(enable);
}
@@ -243,8 +240,7 @@ public class ListMenu extends ListView
public void resetHighlight() {
int count = getChildCount();
for (int i = 0; i < count; i++) {
- View v = getChildAt(i);
- v.setBackground(null);
+ getChildAt(i).setActivated(false);
}
mHighlighted = -1;
}
@@ -265,7 +261,7 @@ public class ListMenu extends ListView
resetHighlight();
ListPreference pref = mListItem.get(position);
mHighlighted = position;
- view.setBackgroundColor(getContext().getResources().getColor(R.color.setting_color));
+ view.setActivated(true);
mListener.onPreferenceClicked(pref, (int) view.getY());
}
@@ -274,11 +270,9 @@ public class ListMenu extends ListView
public void reloadPreference() {
int count = getChildCount();
for (int i = 0; i < count; i++) {
- ListPreference pref = mListItem.get(i);
- if (pref != null) {
- ListMenuItem listMenuItem =
- (ListMenuItem) getChildAt(i);
- listMenuItem.reloadPreference();
+ View view = getChildAt(i);
+ if (view instanceof ListMenuItem) {
+ ((ListMenuItem) view).reloadPreference();
}
}
}
diff --git a/src/com/android/camera/ui/MenuHelp.java b/src/com/android/camera/ui/MenuHelp.java
deleted file mode 100644
index 4adff0fd6..000000000
--- a/src/com/android/camera/ui/MenuHelp.java
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
-Copyright (c) 2016, The Linux Foundation. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- * Neither the name of The Linux Foundation nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-package com.android.camera.ui;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Typeface;
-import android.graphics.drawable.AnimationDrawable;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewPropertyAnimator;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.TableLayout;
-import android.widget.TextView;
-import java.util.ArrayList;
-
-import org.codeaurora.snapcam.R;
-import com.android.camera.ui.ModuleSwitcher;
-import com.android.camera.ui.RotateImageView;
-import com.android.camera.ShutterButton;
-import com.android.camera.Storage;
-import com.android.camera.util.CameraUtil;
-import com.android.camera.TsMakeupManager;
-
-public class MenuHelp extends RotatableLayout {
-
- private static final String TAG = "MenuHelp";
- private View mBackgroundView;
- private Arrows mArrows;
- private static int mTopMargin = 0;
- private static int mBottomMargin = 0;
- private static final int HELP_0_0_INDEX = 0;
- private static final int HELP_1_0_INDEX = 1;
- private static final int HELP_3_0_INDEX = 2;
- private static final int HELP_4_6_INDEX = 3;
- private static final int OK_2_4_INDEX = 4;
- private static final int MAX_INDEX = 5;
- private float[][] mLocX = new float[4][MAX_INDEX];
- private float[][] mLocY = new float[4][MAX_INDEX];
- private RotateLayout mHelp0_0;
- private RotateLayout mHelp1_0;
- private RotateLayout mHelp3_0;
- private RotateLayout mHelp4_6;
- private RotateLayout mOk2_4;
- private Context mContext;
- private int mOrientation;
- private final static int POINT_MARGIN = 50;
- private static final int WIDTH_GRID = 5;
- private static final int HEIGHT_GRID = 7;
- private Typeface mTypeface;
- private boolean forCamera2 = false;
-
- public MenuHelp(Context context, AttributeSet attrs) {
- super(context, attrs);
- mContext = context;
- mTypeface = Typeface.create(Typeface.SERIF, Typeface.NORMAL);
- }
-
- public MenuHelp(Context context) {
- this(context, null);
- }
-
- public void setForCamera2(boolean forCamera2) {
- this.forCamera2 = forCamera2;
- }
-
- public void setMargins(int top, int bottom) {
- mTopMargin = top;
- mBottomMargin = bottom;
- }
-
- @Override
- public void onLayout(boolean changed, int l, int t, int r, int b) {
- r = r - l;
- b = b - t;
- l = 0;
- t = 0;
- for (int i = 0; i < getChildCount(); i++) {
- View v = getChildAt(i);
- v.layout(l, t, r, b);
- }
- setLocation(r - l, b - t);
- }
-
- private void setLocation(int w, int h) {
- int rotation = getUnifiedRotation();
- toIndex(mHelp0_0, w, h, rotation, 1, 3, HELP_0_0_INDEX);
- toIndex(mHelp1_0, w, h, rotation, 2, 2, HELP_1_0_INDEX);
- if(TsMakeupManager.HAS_TS_MAKEUP)
- toIndex(mHelp3_0, w, h, rotation, 3, 1, HELP_3_0_INDEX);
- if (!forCamera2) {
- toIndex(mHelp4_6, w, h, rotation, 3, 4, HELP_4_6_INDEX);
- } else {
- mHelp4_6.setVisibility(View.GONE);
- }
- toIndex(mOk2_4, w, h, rotation, 1, 5, OK_2_4_INDEX);
- fillArrows(w, h, rotation);
- }
-
- private void fillArrows(int w, int h, int rotation) {
- View v1 = new View(mContext);
- View v2 = new View(mContext);
- View v3 = new View(mContext);
- {
- toIndex(v1, w, h, rotation, 1, 3, -1);
- toIndex(v2, w, h, rotation, 0, 1, -1);
- toIndex(v3, w, h, rotation, 0, 0, -1);
- float[] x = {v1.getX()-POINT_MARGIN, v2.getX(), v3.getX()};
- float[] y = {v1.getY()-POINT_MARGIN, v2.getY(), v3.getY()+POINT_MARGIN};
- mArrows.addPath(x, y);
- }
-
- {
- toIndex(v1, w, h, rotation, 2, 2, -1);
- toIndex(v2, w, h, rotation, 1, 1, -1);
- toIndex(v3, w, h, rotation, 1, 0, -1);
- float[] x = {v1.getX()-POINT_MARGIN, v2.getX(), v3.getX()};
- float[] y = {v1.getY()-POINT_MARGIN, v2.getY(), v3.getY()+POINT_MARGIN};
- mArrows.addPath(x, y);
- }
-
- if(TsMakeupManager.HAS_TS_MAKEUP) {
- toIndex(v1, w, h, rotation, 3, 1, -1);
- toIndex(v2, w, h, rotation, 3, 0, -1);
- float[] x = {v1.getX(), v2.getX()};
- float[] y = {v1.getY()-POINT_MARGIN*2, v2.getY()+POINT_MARGIN};
- mArrows.addPath(x, y);
- }
-
- if (!forCamera2) {
- toIndex(v1, w, h, rotation, 3, 4, -1);
- toIndex(v2, w, h, rotation, 3, 5, -1);
- toIndex(v3, w, h, rotation, 4, 6, -1);
- float[] x = {v1.getX(), v2.getX(), v3.getX()};
- float[] y = {v1.getY()+POINT_MARGIN, v2.getY(), v3.getY()-POINT_MARGIN};
- mArrows.addPath(x, y);
- }
- }
-
- private void toIndex(View v, int w, int h, int rotation, int index, int index2, int index3) {
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
- int tw = v.getMeasuredWidth();
- int th = v.getMeasuredHeight();
- int l = 0, r = 0, t = 0, b = 0;
-
- int wnumber = WIDTH_GRID;
- int hnumber = HEIGHT_GRID;
- int windex = 0;
- int hindex = 0;
- switch (rotation) {
- case 0:
- // portrait, to left of anchor at bottom
- wnumber = WIDTH_GRID;
- hnumber = HEIGHT_GRID;
- windex = index;
- hindex = index2;
- break;
- case 90:
- // phone landscape: below anchor on right
- wnumber = HEIGHT_GRID;
- hnumber = WIDTH_GRID;
- windex = index2;
- hindex = hnumber - index - 1;
- break;
- case 180:
- // phone upside down: right of anchor at top
- wnumber = WIDTH_GRID;
- hnumber = HEIGHT_GRID;
- windex = wnumber - index - 1;
- hindex = hnumber - index2 - 1;
- break;
- case 270:
- // reverse landscape: above anchor on left
- wnumber = HEIGHT_GRID;
- hnumber = WIDTH_GRID;
- windex = wnumber - index2 - 1;
- hindex = index;
- break;
- }
- int boxh = h / hnumber;
- int boxw = w / wnumber;
- int cx = (2 * windex + 1) * boxw / 2;
- int cy = (2 * hindex + 1) * boxh / 2;
-
- if (index2 == 0 && mTopMargin != 0) {
- switch (rotation) {
- case 90:
- cx = mTopMargin / 2;
- break;
- case 180:
- cy = h - mTopMargin / 2;
- break;
- case 270:
- cx = w - mTopMargin / 2;
- break;
- default:
- cy = mTopMargin / 2;
- break;
- }
- }
-
- l = cx - tw / 2;
- r = cx + tw / 2;
- t = cy - th / 2;
- b = cy + th / 2;
-
- if (index3 != -1) {
- int idx1 = rotation / 90;
- int idx2 = index3;
- mLocX[idx1][idx2] = l;
- mLocY[idx1][idx2] = t;
- }
- v.layout(l, t, r, b);
- }
-
- public void setOrientation(int orientation, boolean animation) {
- mOrientation = orientation;
- RotateLayout[] layouts = {
- mHelp0_0, mHelp1_0, mHelp3_0, mHelp4_6, mOk2_4
- };
- for (RotateLayout l : layouts) {
- l.setOrientation(orientation, animation);
- }
- }
-
- @Override
- public void onFinishInflate() {
- super.onFinishInflate();
- mBackgroundView = findViewById(R.id.background);
- mBackgroundView.setBackgroundColor(Color.argb(200, 0, 0, 0));
- mHelp0_0 = (RotateLayout)findViewById(R.id.help_text_0_0);
- fillHelp0_0();
- mHelp1_0 = (RotateLayout)findViewById(R.id.help_text_1_0);
- fillHelp1_0();
- mHelp3_0 = (RotateLayout) findViewById(R.id.help_text_3_0);
- fillHelp3_0();
- mHelp4_6 = (RotateLayout)findViewById(R.id.help_text_4_6);
- fillHelp4_6();
- mOk2_4 = (RotateLayout)findViewById(R.id.help_ok_2_4);
- fillOk2_4();
- mArrows = (Arrows)findViewById(R.id.arrows);
- }
-
- private void fillOk2_4() {
- LinearLayout linearLayout = new LinearLayout(mContext);
- mOk2_4.addView(linearLayout);
- linearLayout.setGravity(Gravity.CENTER);
- linearLayout.setPadding(40, 20, 40, 20);
- linearLayout.setBackgroundColor(Color.WHITE);
- TextView text1 = new TextView(mContext);
- text1.setText(getResources().getString(R.string.help_menu_ok));
- text1.setTextColor(Color.BLACK);
- text1.setTypeface(mTypeface);
- linearLayout.addView(text1);
- }
-
- private void fillHelp0_0() {
- TableLayout tableLayout = new TableLayout(mContext);
- mHelp0_0.addView(tableLayout);
- LinearLayout linearLayout = new LinearLayout(mContext);
- TextView text1 = new TextView(mContext);
- text1.setTextColor(getResources().getColor(R.color.help_menu_scene_mode_1));
- text1.setText(getResources().getString(R.string.help_menu_scene_mode_1)+" ");
- text1.setTypeface(mTypeface);
- linearLayout.addView(text1);
- TextView text2 = new TextView(mContext);
- text2.setText(getResources().getString(R.string.help_menu_scene_mode_2));
- text2.setTypeface(mTypeface);
- linearLayout.addView(text2);
- text2.setTextColor(getResources().getColor(R.color.help_menu_scene_mode_2));
- tableLayout.addView(linearLayout);
- TextView text3 = new TextView(mContext);
- text3.setText(getResources().getString(R.string.help_menu_scene_mode_3));
- text3.setTextColor(getResources().getColor(R.color.help_menu_scene_mode_3));
- text3.setTypeface(mTypeface);
- tableLayout.addView(text3);
- }
-
- private void fillHelp1_0() {
- TableLayout tableLayout = new TableLayout(mContext);
- mHelp1_0.addView(tableLayout);
- LinearLayout linearLayout = new LinearLayout(mContext);
- TextView text1 = new TextView(mContext);
- text1.setText(getResources().getString(R.string.help_menu_color_filter_1)+" ");
- text1.setTextColor(getResources().getColor(R.color.help_menu_color_filter_1));
- text1.setTypeface(mTypeface);
- linearLayout.addView(text1);
- TextView text2 = new TextView(mContext);
- text2.setText(getResources().getString(R.string.help_menu_color_filter_2)+" ");
- text2.setTextColor(getResources().getColor(R.color.help_menu_color_filter_2));
- text2.setTypeface(mTypeface);
- linearLayout.addView(text2);
- TextView text3 = new TextView(mContext);
- text3.setText(getResources().getString(R.string.help_menu_color_filter_3));
- text3.setTextColor(getResources().getColor(R.color.help_menu_color_filter_3));
- text3.setTypeface(mTypeface);
- linearLayout.addView(text3);
- tableLayout.addView(linearLayout);
- TextView text4 = new TextView(mContext);
- text4.setText(getResources().getString(R.string.help_menu_color_filter_4));
- text4.setTextColor(getResources().getColor(R.color.help_menu_color_filter_4));
- text4.setTypeface(mTypeface);
- tableLayout.addView(text4);
- }
-
- private void fillHelp3_0() {
- TableLayout tableLayout = new TableLayout(mContext);
- mHelp3_0.addView(tableLayout);
- if(TsMakeupManager.HAS_TS_MAKEUP) {
- TextView text1 = new TextView(mContext);
- text1.setText(getResources().getString(R.string.help_menu_beautify_1));
- text1.setTextColor(getResources().getColor(R.color.help_menu_beautify_1));
- text1.setTypeface(mTypeface);
- tableLayout.addView(text1);
- TextView text2 = new TextView(mContext);
- text2.setText(getResources().getString(R.string.help_menu_beautify_2));
- text2.setTextColor(getResources().getColor(R.color.help_menu_beautify_2));
- text2.setTypeface(mTypeface);
- tableLayout.addView(text2);
- TextView text3 = new TextView(mContext);
- text3.setText(getResources().getString(R.string.help_menu_beautify_3));
- text3.setTextColor(getResources().getColor(R.color.help_menu_beautify_3));
- text3.setTypeface(mTypeface);
- tableLayout.addView(text3);
- }
- }
-
- private void fillHelp4_6() {
- TableLayout tableLayout = new TableLayout(mContext);
- mHelp4_6.addView(tableLayout);
- LinearLayout linearLayout = new LinearLayout(mContext);
- TextView text1 = new TextView(mContext);
- text1.setText(getResources().getString(R.string.help_menu_switcher_1)+" ");
- text1.setTextColor(Color.GREEN);
- text1.setTypeface(mTypeface);
- linearLayout.addView(text1);
- TextView text2 = new TextView(mContext);
- text2.setText(getResources().getString(R.string.help_menu_switcher_2));
- text2.setTextColor(Color.WHITE);
- text2.setTypeface(mTypeface);
- linearLayout.addView(text2);
- tableLayout.addView(linearLayout);
- TextView text3 = new TextView(mContext);
- text3.setText(getResources().getString(R.string.help_menu_switcher_3));
- text3.setTextColor(Color.WHITE);
- text3.setTypeface(mTypeface);
- tableLayout.addView(text3);
- }
-}
diff --git a/src/com/android/camera/ui/ModuleSwitcher.java b/src/com/android/camera/ui/ModuleSwitcher.java
index d96775d14..058e64d7b 100644
--- a/src/com/android/camera/ui/ModuleSwitcher.java
+++ b/src/com/android/camera/ui/ModuleSwitcher.java
@@ -51,10 +51,11 @@ public class ModuleSwitcher extends RotateImageView
public static final int PHOTO_MODULE_INDEX = 0;
public static final int VIDEO_MODULE_INDEX = 1;
public static final int WIDE_ANGLE_PANO_MODULE_INDEX = 2;
- public static final int LIGHTCYCLE_MODULE_INDEX = 3;
- public static final int GCAM_MODULE_INDEX = 4;
- public static final int CAPTURE_MODULE_INDEX = 5;
- public static final int PANOCAPTURE_MODULE_INDEX = 6;
+ public static final int QR_MODULE_INDEX = 3;
+ public static final int LIGHTCYCLE_MODULE_INDEX = 4;
+ public static final int GCAM_MODULE_INDEX = 5;
+ public static final int CAPTURE_MODULE_INDEX = 6;
+ public static final int PANOCAPTURE_MODULE_INDEX = 7;
private boolean mTouchEnabled = true;
private boolean mIsVisible = true;
@@ -63,6 +64,7 @@ public class ModuleSwitcher extends RotateImageView
R.drawable.ic_switch_camera,
R.drawable.ic_switch_video,
R.drawable.ic_switch_pan,
+ R.drawable.ic_cam_switcher_qr,
R.drawable.ic_switch_photosphere,
R.drawable.ic_switch_gcam,
};
@@ -102,7 +104,7 @@ public class ModuleSwitcher extends RotateImageView
private void init(Context context) {
mItemSize = context.getResources().getDimensionPixelSize(R.dimen.switcher_size);
- mIndicator = context.getResources().getDrawable(R.drawable.ic_switcher_menu_indicator);
+ mIndicator = context.getResources().getDrawable(R.color.transparent);
initializeDrawables(context);
}
@@ -231,6 +233,10 @@ public class ModuleSwitcher extends RotateImageView
item.setContentDescription(getContext().getResources().getString(
R.string.accessibility_switch_to_panorama));
break;
+ case R.drawable.ic_cam_switcher_qr:
+ item.setContentDescription(getContext().getResources().getString(
+ R.string.accessibility_switch_to_qr));
+ break;
case R.drawable.ic_switch_photosphere:
item.setContentDescription(getContext().getResources().getString(
R.string.accessibility_switch_to_photo_sphere));
diff --git a/src/com/android/camera/ui/OneUICameraControls.java b/src/com/android/camera/ui/OneUICameraControls.java
index 646596912..73cb68e16 100755
--- a/src/com/android/camera/ui/OneUICameraControls.java
+++ b/src/com/android/camera/ui/OneUICameraControls.java
@@ -232,7 +232,7 @@ public class OneUICameraControls extends RotatableLayout {
mViews = new View[]{
mSceneModeSwitcher, mFilterModeSwitcher, mFrontBackSwitcher,
- mTsMakeupSwitcher,mDeepportraitSwitcher, mFlashButton, mShutter,
+ mTsMakeupSwitcher, mDeepportraitSwitcher, mFlashButton,
mPreview, mVideoShutter, mPauseButton, mCancelButton
};
mBottomLargeSize = getResources().getDimensionPixelSize(
@@ -501,7 +501,7 @@ public class OneUICameraControls extends RotatableLayout {
View[] views = {
mSceneModeSwitcher, mFilterModeSwitcher, mFrontBackSwitcher,
mTsMakeupSwitcher, mFlashButton, mDeepportraitSwitcher, mPreview, mMute,
- mShutter, mVideoShutter, mMakeupSeekBarLowText, mMakeupSeekBarHighText,
+ mMakeupSeekBarLowText, mMakeupSeekBarHighText,
mPauseButton, mExitBestPhotpMode
};
diff --git a/src/com/android/camera/ui/Switch.java b/src/com/android/camera/ui/Switch.java
index 3e7b9bfb9..68fb36542 100644
--- a/src/com/android/camera/ui/Switch.java
+++ b/src/com/android/camera/ui/Switch.java
@@ -123,7 +123,7 @@ public class Switch extends CompoundButton {
mSwitchMinWidth = res.getDimensionPixelSize(R.dimen.switch_min_width);
mSwitchTextMaxWidth = res.getDimensionPixelSize(R.dimen.switch_text_max_width);
mSwitchPadding = res.getDimensionPixelSize(R.dimen.switch_padding);
- setSwitchTextAppearance(context, android.R.style.TextAppearance_Holo_Small);
+ setSwitchTextAppearance(context, android.R.style.TextAppearance_Material_Small);
ViewConfiguration config = ViewConfiguration.get(context);
mTouchSlop = config.getScaledTouchSlop();
diff --git a/src/com/android/camera/ui/ZoomRenderer.java b/src/com/android/camera/ui/ZoomRenderer.java
index 48a565a6f..eb88decc2 100755
--- a/src/com/android/camera/ui/ZoomRenderer.java
+++ b/src/com/android/camera/ui/ZoomRenderer.java
@@ -16,12 +16,15 @@
package com.android.camera.ui;
+import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.Point;
import android.graphics.Rect;
+import android.os.Handler;
import android.view.ScaleGestureDetector;
import org.codeaurora.snapcam.R;
@@ -35,6 +38,8 @@ public class ZoomRenderer extends OverlayRenderer
private int mMinZoom;
private OnZoomChangedListener mListener;
+ private final Handler mHandler = new Handler();
+
private ScaleGestureDetector mDetector;
private Paint mPaint;
private Paint mTextPaint;
@@ -47,12 +52,17 @@ public class ZoomRenderer extends OverlayRenderer
private int mOuterStroke;
private int mZoomSig;
private int mZoomFraction;
+ private boolean mInZoom;
private Rect mTextBounds;
private int mOrientation;
private boolean mCamera2 = false;
private float mZoomMinValue;
private float mZoomMaxValue;
+ private Point mDispSize;
+ private int mBottomMargin;
+ private int mTopMargin;
+
public interface OnZoomChangedListener {
void onZoomStart();
void onZoomEnd();
@@ -77,6 +87,13 @@ public class ZoomRenderer extends OverlayRenderer
mMinCircle = res.getDimensionPixelSize(R.dimen.zoom_ring_min);
mTextBounds = new Rect();
setVisible(false);
+ mBottomMargin =
+ ctx.getResources().getDimensionPixelSize(R.dimen.preview_bottom_margin);
+ mTopMargin =
+ ctx.getResources().getDimensionPixelSize(R.dimen.preview_top_margin);
+ mDispSize = new Point();
+ Activity activity = (Activity) ctx;
+ activity.getWindowManager().getDefaultDisplay().getRealSize(mDispSize);
}
// set from module
@@ -115,9 +132,13 @@ public class ZoomRenderer extends OverlayRenderer
@Override
public void layout(int l, int t, int r, int b) {
+ l = 0;
+ t = mTopMargin;
+ r = mDispSize.x;
+ b = mDispSize.y - mBottomMargin;
super.layout(l, t, r, b);
mCenterX = (r - l) / 2;
- mCenterY = (b - t) / 2;
+ mCenterY = ((b - t) / 2) + t;
mMaxCircle = Math.min(getWidth(), getHeight());
mMaxCircle = (mMaxCircle - mMinCircle) / 2;
}
@@ -165,6 +186,48 @@ public class ZoomRenderer extends OverlayRenderer
return true;
}
+ public boolean onScaleStepResize(boolean direction) {
+ int zoom;
+ float circle;
+ float circleStep = (mMaxCircle - mMinCircle) / 18;
+ if (direction) {
+ circle = (int) (mCircleSize + circleStep);
+ } else {
+ circle = (int) (mCircleSize - circleStep);
+ }
+ circle = Math.max(mMinCircle, circle);
+ circle = Math.min(mMaxCircle, circle);
+ if (mListener != null && (int) circle != mCircleSize && (mMaxCircle - mMinCircle) > 0) {
+ mCircleSize = (int) circle;
+ zoom = mMinZoom + (int) ((mCircleSize - mMinCircle)
+ * (mMaxZoom - mMinZoom) / (mMaxCircle - mMinCircle));
+ if (mListener != null) {
+ mHandler.removeCallbacks(mOnZoomEnd);
+ if (!mInZoom) {
+ mInZoom = true;
+ setVisible(true);
+ mListener.onZoomStart();
+ update();
+ }
+ mListener.onZoomValueChanged(zoom);
+ mHandler.postDelayed(mOnZoomEnd, 300);
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ Runnable mOnZoomEnd = new Runnable() {
+ public void run() {
+ mInZoom = false;
+ setVisible(false);
+ if (mListener != null) {
+ mListener.onZoomEnd();
+ }
+ }
+ };
+
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
setVisible(true);
diff --git a/src/com/android/camera/ui/focus/AutoFocusRing.java b/src/com/android/camera/ui/focus/AutoFocusRing.java
new file mode 100644
index 000000000..ff09ebc65
--- /dev/null
+++ b/src/com/android/camera/ui/focus/AutoFocusRing.java
@@ -0,0 +1,101 @@
+/*
+ * 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.ui.focus;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+
+import com.android.camera.ui.motion.InterpolateUtils;
+import com.android.camera.ui.motion.Invalidator;
+
+/**
+ * Passive focus ring animation renderer.
+ */
+class AutoFocusRing extends FocusRingRenderer {
+ private static final String TAG = "AutoFocusRing";
+
+ /**
+ * The auto focus ring encapsulates the animation logic for visualizing
+ * a focus event when triggered by the camera subsystem.
+ *
+ * @param invalidator the object to invalidate while running.
+ * @param ringPaint the paint to draw the ring with.
+ * @param enterDurationMillis the fade in time in milliseconds.
+ * @param exitDurationMillis the fade out time in milliseconds.
+ */
+ public AutoFocusRing(Invalidator invalidator, Paint ringPaint, float enterDurationMillis,
+ float exitDurationMillis) {
+ super(invalidator, ringPaint, enterDurationMillis, exitDurationMillis);
+ }
+
+ @Override
+ public void draw(long t, long dt, Canvas canvas) {
+ float ringRadius = mRingRadius.update(dt);
+ processStates(t);
+
+ if (!isActive()) {
+ return;
+ }
+
+ mInvalidator.invalidate();
+ int ringAlpha = 255;
+
+ if (mFocusState == FocusState.STATE_ENTER) {
+ float rFade = InterpolateUtils.unitRatio(t, mEnterStartMillis, mEnterDurationMillis);
+ ringAlpha = (int) InterpolateUtils
+ .lerp(0, 255, mEnterOpacityCurve.valueAt(rFade));
+ } else if (mFocusState == FocusState.STATE_FADE_OUT) {
+ float rFade = InterpolateUtils.unitRatio(t, mExitStartMillis, mExitDurationMillis);
+ ringAlpha = (int) InterpolateUtils
+ .lerp(255, 0, mExitOpacityCurve.valueAt(rFade));
+ } else if (mFocusState == FocusState.STATE_HARD_STOP) {
+ float rFade = InterpolateUtils
+ .unitRatio(t, mHardExitStartMillis, mHardExitDurationMillis);
+ ringAlpha = (int) InterpolateUtils
+ .lerp(255, 0, mExitOpacityCurve.valueAt(rFade));
+ } else if (mFocusState == FocusState.STATE_INACTIVE) {
+ ringAlpha = 0;
+ }
+
+ mRingPaint.setAlpha(ringAlpha);
+ canvas.drawCircle(getCenterX(), getCenterY(), ringRadius, mRingPaint);
+ }
+
+ private void processStates(long t) {
+ if (mFocusState == FocusState.STATE_INACTIVE) {
+ return;
+ }
+
+ if (mFocusState == FocusState.STATE_ENTER && t > mEnterStartMillis + mEnterDurationMillis) {
+ mFocusState = FocusState.STATE_ACTIVE;
+ }
+
+ if (mFocusState == FocusState.STATE_ACTIVE && !mRingRadius.isActive()) {
+ mFocusState = FocusState.STATE_FADE_OUT;
+ mExitStartMillis = t;
+ }
+
+ if (mFocusState == FocusState.STATE_FADE_OUT && t > mExitStartMillis + mExitDurationMillis) {
+ mFocusState = FocusState.STATE_INACTIVE;
+ }
+
+ if (mFocusState == FocusState.STATE_HARD_STOP
+ && t > mHardExitStartMillis + mHardExitDurationMillis) {
+ mFocusState = FocusState.STATE_INACTIVE;
+ }
+ }
+}
diff --git a/src/com/android/camera/ui/focus/CameraCoordinateTransformer.java b/src/com/android/camera/ui/focus/CameraCoordinateTransformer.java
new file mode 100644
index 000000000..809503c9a
--- /dev/null
+++ b/src/com/android/camera/ui/focus/CameraCoordinateTransformer.java
@@ -0,0 +1,109 @@
+/*
+ * 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.ui.focus;
+
+import android.graphics.Matrix;
+import android.graphics.RectF;
+
+/**
+ * Transform coordinates to and from preview coordinate space and camera driver
+ * coordinate space.
+ */
+public class CameraCoordinateTransformer {
+ // http://developer.android.com/guide/topics/media/camera.html#metering-focus-areas
+ private static final RectF CAMERA_DRIVER_RECT = new RectF(-1000, -1000, 1000, 1000);
+
+ private final Matrix mCameraToPreviewTransform;
+ private final Matrix mPreviewToCameraTransform;
+
+ /**
+ * Convert rectangles to / from camera coordinate and preview coordinate space.
+ *
+ * @param mirrorX if the preview is mirrored along the X axis.
+ * @param displayOrientation orientation in degrees.
+ * @param previewRect the preview rectangle size and position.
+ */
+ public CameraCoordinateTransformer(boolean mirrorX, int displayOrientation,
+ RectF previewRect) {
+ if (!hasNonZeroArea(previewRect)) {
+ throw new IllegalArgumentException("previewRect");
+ }
+
+ mCameraToPreviewTransform = cameraToPreviewTransform(mirrorX, displayOrientation,
+ previewRect);
+ mPreviewToCameraTransform = inverse(mCameraToPreviewTransform);
+ }
+
+ /**
+ * Transform a rectangle in camera space into a new rectangle in preview
+ * view space.
+ *
+ * @param source the rectangle in camera space
+ * @return the rectangle in preview view space.
+ */
+ public RectF toPreviewSpace(RectF source) {
+ RectF result = new RectF();
+ mCameraToPreviewTransform.mapRect(result, source);
+ return result;
+ }
+
+ /**
+ * Transform a rectangle in preview view space into a new rectangle in
+ * camera view space.
+ *
+ * @param source the rectangle in preview view space
+ * @return the rectangle in camera view space.
+ */
+ public RectF toCameraSpace(RectF source) {
+ RectF result = new RectF();
+ mPreviewToCameraTransform.mapRect(result, source);
+ return result;
+ }
+
+ private Matrix cameraToPreviewTransform(boolean mirrorX, int displayOrientation,
+ RectF previewRect) {
+ Matrix transform = new Matrix();
+
+ // Need mirror for front camera.
+ transform.setScale(mirrorX ? -1 : 1, 1);
+
+ // Apply a rotate transform.
+ // This is the value for android.hardware.Camera.setDisplayOrientation.
+ transform.postRotate(displayOrientation);
+
+ // Map camera driver coordinates to preview rect coordinates
+ Matrix fill = new Matrix();
+ fill.setRectToRect(CAMERA_DRIVER_RECT,
+ previewRect,
+ Matrix.ScaleToFit.FILL);
+
+ // Concat the previous transform on top of the fill behavior.
+ transform.setConcat(fill, transform);
+
+ return transform;
+ }
+
+ private Matrix inverse(Matrix source) {
+ Matrix newMatrix = new Matrix();
+ source.invert(newMatrix);
+ return newMatrix;
+ }
+
+ private boolean hasNonZeroArea(RectF rect) {
+ return rect.width() != 0 && rect.height() != 0;
+ }
+}
diff --git a/src/com/android/camera/ui/focus/FocusController.java b/src/com/android/camera/ui/focus/FocusController.java
new file mode 100644
index 000000000..a0c103443
--- /dev/null
+++ b/src/com/android/camera/ui/focus/FocusController.java
@@ -0,0 +1,128 @@
+/*
+ * 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.ui.focus;
+
+import android.graphics.RectF;
+import android.util.Log;
+
+import com.android.camera.async.MainThread;
+import com.android.camera.ui.motion.LinearScale;
+
+/**
+ * The focus controller interacts with the focus ring UI element.
+ */
+public class FocusController {
+ private static final String TAG = "FocusController";
+
+ private final FocusRing mFocusRing;
+ private final FocusSound mFocusSound;
+ private final MainThread mMainThread;
+
+ public FocusController(FocusRing focusRing, FocusSound focusSound, MainThread mainThread) {
+ mFocusRing = focusRing;
+ mFocusSound = focusSound;
+ mMainThread = mainThread;
+ }
+
+ /**
+ * Show a passive focus animation at the center of the active area.
+ * This will likely be different than the view bounds due to varying image
+ * ratios and dimensions.
+ */
+ public void showPassiveFocusAtCenter() {
+ mMainThread.execute(new Runnable() {
+ @Override
+ public void run() {
+ Log.v(TAG, "Running showPassiveFocusAtCenter()");
+ mFocusRing.startPassiveFocus();
+ mFocusRing.centerFocusLocation();
+ }
+ });
+ }
+
+ /**
+ * Show a passive focus animation at the given viewX and viewY position.
+ * This is usually indicates the camera subsystem kicked off an auto-focus
+ * at the given screen position.
+ *
+ * @param viewX the view's x coordinate
+ * @param viewY the view's y coordinate
+ */
+ public void showPassiveFocusAt(final int viewX, final int viewY) {
+ mMainThread.execute(new Runnable() {
+ @Override
+ public void run() {
+ Log.v(TAG, "Running showPassiveFocusAt(" + viewX + ", " + viewY + ")");
+ mFocusRing.startPassiveFocus();
+ mFocusRing.setFocusLocation(viewX, viewY);
+ }
+ });
+ }
+
+ /**
+ * Show an active focus animation at the given viewX and viewY position.
+ * This is normally initiated by the user touching the screen at a given
+ * point.
+ *
+ * @param viewX the view's x coordinate
+ * @param viewY the view's y coordinate
+ */
+ public void showActiveFocusAt(final int viewX, final int viewY) {
+ mMainThread.execute(new Runnable() {
+ @Override
+ public void run() {
+ Log.v(TAG, "showActiveFocusAt(" + viewX + ", " + viewY + ")");
+ mFocusRing.startActiveFocus();
+ mFocusRing.setFocusLocation(viewX, viewY);
+
+ // TODO: Enable focus sound when better audio controls exist.
+ // mFocusSound.play();
+ }
+ });
+ }
+
+ /**
+ * Computing the correct location for the focus ring requires knowing
+ * the screen position and size of the preview area so the drawing
+ * operations can be clipped correctly.
+ */
+ public void configurePreviewDimensions(final RectF previewArea) {
+ mMainThread.execute(new Runnable() {
+ @Override
+ public void run() {
+ Log.v(TAG, "configurePreviewDimensions(" + previewArea + ")");
+ mFocusRing.configurePreviewDimensions(previewArea);
+ }
+ });
+ }
+
+ /**
+ * Set the radius of the focus ring as a radius between 0 and 1.
+ * This will map to the min and max values computed for the UI.
+ */
+ public void setFocusRatio(final float ratio) {
+ mMainThread.execute(new Runnable() {
+ @Override
+ public void run() {
+ if (mFocusRing.isPassiveFocusRunning() ||
+ mFocusRing.isActiveFocusRunning()) {
+ mFocusRing.setRadiusRatio(ratio);
+ }
+ }
+ });
+ }
+}
diff --git a/src/com/android/camera/ui/focus/FocusRing.java b/src/com/android/camera/ui/focus/FocusRing.java
new file mode 100644
index 000000000..89de357ad
--- /dev/null
+++ b/src/com/android/camera/ui/focus/FocusRing.java
@@ -0,0 +1,72 @@
+/*
+ * 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.ui.focus;
+
+import android.graphics.RectF;
+
+/**
+ * Primary interface for interacting with the focus ring UI.
+ */
+public interface FocusRing {
+ /**
+ * Check the state of the passive focus ring animation.
+ *
+ * @return whether the passive focus animation is running.
+ */
+ public boolean isPassiveFocusRunning();
+ /**
+ * Check the state of the active focus ring animation.
+ *
+ * @return whether the active focus animation is running.
+ */
+ public boolean isActiveFocusRunning();
+ /**
+ * Start a passive focus animation.
+ */
+ public void startPassiveFocus();
+ /**
+ * Start an active focus animation.
+ */
+ public void startActiveFocus();
+ /**
+ * Stop any currently running focus animations.
+ */
+ public void stopFocusAnimations();
+ /**
+ * Set the location of the focus ring animation center.
+ */
+ public void setFocusLocation(float viewX, float viewY);
+
+ /**
+ * Set the location of the focus ring animation center.
+ */
+ public void centerFocusLocation();
+
+ /**
+ * Set the target radius as a ratio of min to max visible radius
+ * which will internally convert and clamp the value to the
+ * correct pixel radius.
+ */
+ public void setRadiusRatio(float ratio);
+
+ /**
+ * The physical size of preview can vary and does not map directly
+ * to the size of the view. This allows for conversions between view
+ * and preview space for values that are provided in preview space.
+ */
+ void configurePreviewDimensions(RectF previewArea);
+} \ No newline at end of file
diff --git a/src/com/android/camera/ui/focus/FocusRingRenderer.java b/src/com/android/camera/ui/focus/FocusRingRenderer.java
new file mode 100644
index 000000000..264af2ace
--- /dev/null
+++ b/src/com/android/camera/ui/focus/FocusRingRenderer.java
@@ -0,0 +1,237 @@
+/*
+ * 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.ui.focus;
+
+import android.graphics.Paint;
+import android.util.Log;
+
+import com.android.camera.ui.motion.DampedSpring;
+import com.android.camera.ui.motion.DynamicAnimation;
+import com.android.camera.ui.motion.Invalidator;
+import com.android.camera.ui.motion.UnitCurve;
+import com.android.camera.ui.motion.UnitCurves;
+
+/**
+ * Base class for defining the focus ring states, enter and exit durations, and
+ * positioning logic.
+ */
+abstract class FocusRingRenderer implements DynamicAnimation {
+ private static final String TAG = "FocusRingRenderer";
+
+ /**
+ * Primary focus states that a focus ring renderer can go through.
+ */
+ protected static enum FocusState {
+ STATE_INACTIVE,
+ STATE_ENTER,
+ STATE_ACTIVE,
+ STATE_FADE_OUT,
+ STATE_HARD_STOP,
+ }
+
+ protected final Invalidator mInvalidator;
+ protected final Paint mRingPaint;
+ protected final DampedSpring mRingRadius;
+ protected final UnitCurve mEnterOpacityCurve;
+ protected final UnitCurve mExitOpacityCurve;
+ protected final UnitCurve mHardExitOpacityCurve;
+ protected final float mEnterDurationMillis;
+ protected final float mExitDurationMillis;
+ protected final float mHardExitDurationMillis = 64;
+
+ private int mCenterX;
+ private int mCenterY;
+ protected long mEnterStartMillis = 0;
+ protected long mExitStartMillis = 0;
+ protected long mHardExitStartMillis = 0;
+
+ protected FocusState mFocusState = FocusState.STATE_INACTIVE;
+
+ /**
+ * A dynamic, configurable, self contained ring render that will inform
+ * via invalidation if it should continue to be receive updates
+ * and re-draws.
+ *
+ * @param invalidator the object to inform if it requires more draw calls.
+ * @param ringPaint the paint to use to draw the ring.
+ * @param enterDurationMillis the fade in duration in milliseconds
+ * @param exitDurationMillis the fade out duration in milliseconds.
+ */
+ FocusRingRenderer(Invalidator invalidator, Paint ringPaint, float enterDurationMillis,
+ float exitDurationMillis) {
+ mInvalidator = invalidator;
+ mRingPaint = ringPaint;
+ mEnterDurationMillis = enterDurationMillis;
+ mExitDurationMillis = exitDurationMillis;
+
+ mEnterOpacityCurve = UnitCurves.FAST_OUT_SLOW_IN;
+ mExitOpacityCurve = UnitCurves.FAST_OUT_LINEAR_IN;
+ mHardExitOpacityCurve = UnitCurves.FAST_OUT_LINEAR_IN;
+
+ mRingRadius = new DampedSpring();
+ }
+
+ /**
+ * Set the centerX position for this focus ring renderer.
+ *
+ * @param value the x position
+ */
+ public void setCenterX(int value) {
+ mCenterX = value;
+ }
+
+ protected int getCenterX() {
+ return mCenterX;
+ }
+
+ /**
+ * Set the centerY position for this focus ring renderer.
+ *
+ * @param value the y position
+ */
+ public void setCenterY(int value) {
+ mCenterY = value;
+ }
+
+ protected int getCenterY() {
+ return mCenterY;
+ }
+
+ /**
+ * Set the physical radius of this ring.
+ *
+ * @param value the radius of the ring.
+ */
+ public void setRadius(long tMs, float value) {
+ if (mFocusState == FocusState.STATE_FADE_OUT
+ && Math.abs(mRingRadius.getTarget() - value) > 0.1) {
+ Log.v(TAG, "FOCUS STATE ENTER VIA setRadius(" + tMs + ", " + value + ")");
+ mFocusState = FocusState.STATE_ENTER;
+ mEnterStartMillis = computeEnterStartTimeMillis(tMs, mEnterDurationMillis);
+ }
+
+ mRingRadius.setTarget(value);
+ }
+
+ /**
+ * returns true if the renderer is not in an inactive state.
+ */
+ @Override
+ public boolean isActive() {
+ return mFocusState != FocusState.STATE_INACTIVE;
+ }
+
+ /**
+ * returns true if the renderer is in an exit state.
+ */
+ public boolean isExiting() {
+ return mFocusState == FocusState.STATE_FADE_OUT
+ || mFocusState == FocusState.STATE_HARD_STOP;
+ }
+
+ /**
+ * returns true if the renderer is in an enter state.
+ */
+ public boolean isEntering() {
+ return mFocusState == FocusState.STATE_ENTER;
+ }
+
+ /**
+ * Initialize and start the animation with the given start and
+ * target radius.
+ */
+ public void start(long startMs, float initialRadius, float targetRadius) {
+ if (mFocusState != FocusState.STATE_INACTIVE) {
+ Log.w(TAG, "start() called while the ring was still focusing!");
+ }
+ mRingRadius.stop();
+ mRingRadius.setValue(initialRadius);
+ mRingRadius.setTarget(targetRadius);
+ mEnterStartMillis = startMs;
+
+ mFocusState = FocusState.STATE_ENTER;
+ mInvalidator.invalidate();
+ }
+
+ /**
+ * Put the animation in the exit state regardless of the current
+ * dynamic transition. If the animation is currently in an enter state
+ * this will compute an exit start time such that the exit time lines
+ * up with the enter time at the current transition value.
+ *
+ * @param t the current animation time.
+ */
+ public void exit(long t) {
+ if (mRingRadius.isActive()) {
+ mRingRadius.stop();
+ }
+
+ mFocusState = FocusState.STATE_FADE_OUT;
+ mExitStartMillis = computeExitStartTimeMs(t, mExitDurationMillis);
+ }
+
+ /**
+ * Put the animation in the hard stop state regardless of the current
+ * dynamic transition. If the animation is currently in an enter state
+ * this will compute an exit start time such that the exit time lines
+ * up with the enter time at the current transition value.
+ *
+ * @param tMillis the current animation time in milliseconds.
+ */
+ public void stop(long tMillis) {
+ if (mRingRadius.isActive()) {
+ mRingRadius.stop();
+ }
+
+ mFocusState = FocusState.STATE_HARD_STOP;
+ mHardExitStartMillis = computeExitStartTimeMs(tMillis, mHardExitDurationMillis);
+ }
+
+ private long computeExitStartTimeMs(long tMillis, float exitDuration) {
+ if (mEnterStartMillis + mEnterDurationMillis <= tMillis) {
+ return tMillis;
+ }
+
+ // Compute the current progress on the enter animation.
+ float enterT = (tMillis - mEnterStartMillis) / mEnterDurationMillis;
+
+ // Find a time on the exit curve such that it will produce the same value.
+ float exitT = UnitCurves.mapEnterCurveToExitCurveAtT(mEnterOpacityCurve, mExitOpacityCurve,
+ enterT);
+
+ // Compute the a start time before tMs such that the ratio of time completed
+ // equals the computed exit curve animation position.
+ return tMillis - (long) (exitT * exitDuration);
+ }
+
+ private long computeEnterStartTimeMillis(long tMillis, float enterDuration) {
+ if (mExitStartMillis + mExitDurationMillis <= tMillis) {
+ return tMillis;
+ }
+
+ // Compute the current progress on the enter animation.
+ float exitT = (tMillis - mExitStartMillis) / mExitDurationMillis;
+
+ // Find a time on the exit curve such that it will produce the same value.
+ float enterT = UnitCurves.mapEnterCurveToExitCurveAtT(mExitOpacityCurve, mEnterOpacityCurve,
+ exitT);
+
+ // Compute the a start time before tMs such that the ratio of time completed
+ // equals the computed exit curve animation position.
+ return tMillis - (long) (enterT * enterDuration);
+ }
+}
diff --git a/src/com/android/camera/ui/focus/FocusRingView.java b/src/com/android/camera/ui/focus/FocusRingView.java
new file mode 100644
index 000000000..14a7f6cc9
--- /dev/null
+++ b/src/com/android/camera/ui/focus/FocusRingView.java
@@ -0,0 +1,211 @@
+/*
+ * 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.ui.focus;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+
+import com.android.camera.ui.motion.AnimationClock.SystemTimeClock;
+import com.android.camera.ui.motion.DynamicAnimator;
+import com.android.camera.ui.motion.Invalidator;
+import com.android.camera.ui.motion.LinearScale;
+
+import org.codeaurora.snapcam.R;
+
+/**
+ * Custom view for running the focus ring animations.
+ */
+public class FocusRingView extends View implements Invalidator, FocusRing {
+ private static final String TAG = "FocusRingView";
+ private static final float FADE_IN_DURATION_MILLIS = 1000f;
+ private static final float FADE_OUT_DURATION_MILLIS = 250f;
+
+ private final AutoFocusRing mAutoFocusRing;
+ private final ManualFocusRing mManualFocusRing;
+ private final DynamicAnimator mAnimator;
+ private final LinearScale mRatioScale;
+ private final float mDefaultRadiusPx;
+
+ private FocusRingRenderer currentFocusAnimation;
+ private boolean isFirstDraw;
+ private float mLastRadiusPx;
+
+ private RectF mPreviewSize;
+
+ public FocusRingView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ Resources res = getResources();
+ Paint paint = makePaint(res, R.color.focus_color);
+
+ float focusCircleMinSize = res.getDimensionPixelSize(R.dimen.focus_circle_min_size);
+ float focusCircleMaxSize = res.getDimensionPixelSize(R.dimen.focus_circle_max_size);
+ mDefaultRadiusPx = res.getDimensionPixelSize(R.dimen.focus_circle_initial_size);
+
+ mRatioScale = new LinearScale(0, 1, focusCircleMinSize, focusCircleMaxSize);
+ mAnimator = new DynamicAnimator(this, new SystemTimeClock());
+
+ mAutoFocusRing = new AutoFocusRing(mAnimator, paint,
+ FADE_IN_DURATION_MILLIS,
+ FADE_OUT_DURATION_MILLIS);
+ mManualFocusRing = new ManualFocusRing(mAnimator, paint,
+ FADE_OUT_DURATION_MILLIS);
+
+ mAnimator.animations.add(mAutoFocusRing);
+ mAnimator.animations.add(mManualFocusRing);
+
+ isFirstDraw = true;
+ mLastRadiusPx = mDefaultRadiusPx;
+ }
+
+ @Override
+ public boolean isPassiveFocusRunning() {
+ return mAutoFocusRing.isActive();
+ }
+
+ @Override
+ public boolean isActiveFocusRunning() {
+ return mManualFocusRing.isActive();
+ }
+
+ @Override
+ public void startPassiveFocus() {
+ mAnimator.invalidate();
+ long tMs = mAnimator.getTimeMillis();
+
+ if (mManualFocusRing.isActive() && !mManualFocusRing.isExiting()) {
+ mManualFocusRing.stop(tMs);
+ }
+
+ mAutoFocusRing.start(tMs, mLastRadiusPx, mLastRadiusPx);
+ currentFocusAnimation = mAutoFocusRing;
+ }
+
+ @Override
+ public void startActiveFocus() {
+ mAnimator.invalidate();
+ long tMs = mAnimator.getTimeMillis();
+
+ if (mAutoFocusRing.isActive() && !mAutoFocusRing.isExiting()) {
+ mAutoFocusRing.stop(tMs);
+ }
+
+ mManualFocusRing.start(tMs, 0.0f, mLastRadiusPx);
+ currentFocusAnimation = mManualFocusRing;
+ }
+
+ @Override
+ public void stopFocusAnimations() {
+ long tMs = mAnimator.getTimeMillis();
+ if (mManualFocusRing.isActive() && !mManualFocusRing.isExiting()
+ && !mManualFocusRing.isEntering()) {
+ mManualFocusRing.exit(tMs);
+ }
+
+ if (mAutoFocusRing.isActive() && !mAutoFocusRing.isExiting()) {
+ mAutoFocusRing.exit(tMs);
+ }
+ }
+
+ @Override
+ public void setFocusLocation(float viewX, float viewY) {
+ mAutoFocusRing.setCenterX((int) viewX);
+ mAutoFocusRing.setCenterY((int) viewY);
+ mManualFocusRing.setCenterX((int) viewX);
+ mManualFocusRing.setCenterY((int) viewY);
+ }
+
+ @Override
+ public void centerFocusLocation() {
+ Point center = computeCenter();
+ mAutoFocusRing.setCenterX(center.x);
+ mAutoFocusRing.setCenterY(center.y);
+ mManualFocusRing.setCenterX(center.x);
+ mManualFocusRing.setCenterY(center.y);
+ }
+
+ @Override
+ public void setRadiusRatio(float ratio) {
+ setRadius(mRatioScale.scale(mRatioScale.clamp(ratio)));
+ }
+
+ @Override
+ public void configurePreviewDimensions(RectF previewArea) {
+ mPreviewSize = previewArea;
+ mLastRadiusPx = mDefaultRadiusPx;
+
+ if (!isFirstDraw) {
+ centerAutofocusRing();
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (isFirstDraw) {
+ isFirstDraw = false;
+ centerAutofocusRing();
+ }
+
+ if (mPreviewSize != null) {
+ canvas.clipRect(mPreviewSize, Region.Op.REPLACE);
+ }
+
+ mAnimator.draw(canvas);
+ }
+
+ private void setRadius(float radiusPx) {
+ long tMs = mAnimator.getTimeMillis();
+ // Some devices return zero for invalid or "unknown" diopter values.
+ if (currentFocusAnimation != null && radiusPx > 0.1f) {
+ currentFocusAnimation.setRadius(tMs, radiusPx);
+ mLastRadiusPx = radiusPx;
+ }
+ }
+
+ private void centerAutofocusRing() {
+ Point center = computeCenter();
+ mAutoFocusRing.setCenterX(center.x);
+ mAutoFocusRing.setCenterY(center.y);
+ }
+
+ private Point computeCenter() {
+ if (mPreviewSize != null && (mPreviewSize.width() * mPreviewSize.height() > 0.01f)) {
+ Log.i(TAG, "Computing center via preview size.");
+ return new Point((int) mPreviewSize.centerX(), (int) mPreviewSize.centerY());
+ }
+ Log.i(TAG, "Computing center via view bounds.");
+ return new Point(getWidth() / 2, getHeight() / 2);
+ }
+
+ private Paint makePaint(Resources res, int color) {
+ Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setColor(res.getColor(color));
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setStrokeCap(Paint.Cap.ROUND);
+ paint.setStrokeWidth(res.getDimension(R.dimen.focus_circle_stroke));
+ return paint;
+ }
+}
diff --git a/src/com/android/camera/ui/focus/FocusSound.java b/src/com/android/camera/ui/focus/FocusSound.java
new file mode 100644
index 000000000..c3ff0107d
--- /dev/null
+++ b/src/com/android/camera/ui/focus/FocusSound.java
@@ -0,0 +1,47 @@
+/*
+ * 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.ui.focus;
+
+import com.android.camera.SoundPlayer;
+
+/**
+ * Wraps the focus sound and the player into a single object that can
+ * be played on demand.
+ *
+ * TODO: This needs some way to better manage the sound lifetimes
+ */
+public class FocusSound {
+ private static final float DEFAULT_VOLUME = 0.6f;
+ private final SoundPlayer mPlayer;
+ private final int mSoundId;
+ public FocusSound(SoundPlayer player, int soundId) {
+ mPlayer = player;
+ mSoundId = soundId;
+
+ mPlayer.loadSound(mSoundId);
+ }
+
+ /**
+ * Play the focus sound with the sound player at the default
+ * volume.
+ */
+ public void play() {
+ if(!mPlayer.isReleased()) {
+ mPlayer.play(mSoundId, DEFAULT_VOLUME);
+ }
+ }
+}
diff --git a/src/com/android/camera/ui/focus/LensRangeCalculator.java b/src/com/android/camera/ui/focus/LensRangeCalculator.java
new file mode 100644
index 000000000..ef9cbaec7
--- /dev/null
+++ b/src/com/android/camera/ui/focus/LensRangeCalculator.java
@@ -0,0 +1,71 @@
+/*
+ * 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.ui.focus;
+
+import android.annotation.TargetApi;
+import android.hardware.camera2.CameraCharacteristics;
+import android.os.Build.VERSION_CODES;
+
+import com.android.camera.ui.motion.LinearScale;
+
+/**
+ * Compute diopter range scale to convert lens focus distances into
+ * a ratio value.
+ */
+@TargetApi(VERSION_CODES.LOLLIPOP)
+public class LensRangeCalculator {
+
+ /**
+ * A NoOp linear scale for computing diopter values will always return 0
+ */
+ public static LinearScale getNoOp() {
+ return new LinearScale(0, 0, 0, 0);
+ }
+
+ /**
+ * Compute the focus range from the camera characteristics and build
+ * a linear scale model that maps a focus distance to a ratio between
+ * the min and max range.
+ */
+ public static LinearScale getDiopterToRatioCalculator(CameraCharacteristics characteristics) {
+ // From the android documentation:
+ //
+ // 0.0f represents farthest focus, and LENS_INFO_MINIMUM_FOCUS_DISTANCE
+ // represents the nearest focus the device can achieve.
+ //
+ // Example:
+ //
+ // Infinity Hyperfocal Minimum Camera
+ // <----------|-----------------------------| |
+ // [0.0] [0.31] [14.29]
+ Float nearest = characteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
+ Float hyperfocal = characteristics.get(CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE);
+
+ if (nearest == null && hyperfocal == null) {
+ return getNoOp();
+ }
+
+ nearest = (nearest == null) ? 0.0f : nearest;
+ hyperfocal = (hyperfocal == null) ? 0.0f : hyperfocal;
+
+ if (nearest > hyperfocal) {
+ return new LinearScale(hyperfocal, nearest, 0, 1);
+ }
+
+ return new LinearScale(nearest, hyperfocal, 0, 1);
+ }
+}
diff --git a/src/com/android/camera/ui/focus/ManualFocusRing.java b/src/com/android/camera/ui/focus/ManualFocusRing.java
new file mode 100644
index 000000000..0133d8e09
--- /dev/null
+++ b/src/com/android/camera/ui/focus/ManualFocusRing.java
@@ -0,0 +1,93 @@
+/*
+ * 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.ui.focus;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+
+import com.android.camera.ui.motion.InterpolateUtils;
+import com.android.camera.ui.motion.Invalidator;
+
+/**
+ * Manual focus ring animation renderer.
+ */
+class ManualFocusRing extends FocusRingRenderer {
+ /**
+ * The manual focus ring encapsulates the animation logic for visualizing
+ * a focus event when triggered by a physical screen touch.
+ *
+ * @param invalidator the object to invalidate while running.
+ * @param ringPaint the paint to draw the ring with.
+ * @param exitDurationMillis the fade out time in milliseconds.
+ */
+ public ManualFocusRing(Invalidator invalidator, Paint ringPaint,
+ float exitDurationMillis) {
+ super(invalidator, ringPaint, 0.0f, exitDurationMillis);
+ }
+
+ @Override
+ public void draw(long t, long dt, Canvas canvas) {
+ float ringRadius = mRingRadius.update(dt);
+ processStates(t);
+
+ if (!isActive()) {
+ return;
+ }
+
+ mInvalidator.invalidate();
+ int ringAlpha = 255;
+
+ if (mFocusState == FocusState.STATE_FADE_OUT) {
+ float rFade = InterpolateUtils.unitRatio(t, mExitStartMillis, mExitDurationMillis);
+ ringAlpha = (int) InterpolateUtils.lerp(255, 0, mExitOpacityCurve.valueAt(rFade));
+ } else if (mFocusState == FocusState.STATE_HARD_STOP) {
+ float rFade = InterpolateUtils.unitRatio(t, mHardExitStartMillis,
+ mHardExitDurationMillis);
+ ringAlpha = (int) InterpolateUtils.lerp(255, 0, mExitOpacityCurve.valueAt(rFade));
+ } else if (mFocusState == FocusState.STATE_INACTIVE) {
+ ringAlpha = 0;
+ }
+
+ mRingPaint.setAlpha(ringAlpha);
+ canvas.drawCircle(getCenterX(), getCenterY(), ringRadius, mRingPaint);
+ }
+
+ private void processStates(long t) {
+ if (mFocusState == FocusState.STATE_INACTIVE) {
+ return;
+ }
+
+ if (mFocusState == FocusState.STATE_ENTER
+ && (t > mEnterStartMillis + mEnterDurationMillis)) {
+ mFocusState = FocusState.STATE_ACTIVE;
+ }
+
+ if (mFocusState == FocusState.STATE_ACTIVE && !mRingRadius.isActive()) {
+ mFocusState = FocusState.STATE_FADE_OUT;
+ mExitStartMillis = t;
+ }
+
+ if (mFocusState == FocusState.STATE_FADE_OUT && t > mExitStartMillis + mExitDurationMillis) {
+ mFocusState = FocusState.STATE_INACTIVE;
+ }
+
+ if (mFocusState == FocusState.STATE_HARD_STOP
+ && t > mHardExitStartMillis + mHardExitDurationMillis) {
+ mFocusState = FocusState.STATE_INACTIVE;
+ }
+ }
+}
diff --git a/src/com/android/camera/ui/motion/AnimationClock.java b/src/com/android/camera/ui/motion/AnimationClock.java
new file mode 100644
index 000000000..d2504de6b
--- /dev/null
+++ b/src/com/android/camera/ui/motion/AnimationClock.java
@@ -0,0 +1,39 @@
+/*
+ * 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.ui.motion;
+
+import android.os.SystemClock;
+
+/**
+ * Wraps the SystemClock static time methods so they can be exercised in tests.
+ */
+public abstract class AnimationClock {
+
+ public abstract long getTimeMillis();
+
+ /**
+ * Forwards calls to SystemClock.uptimeMillis() since it is the most consistent clock for
+ * animations.
+ */
+ public static class SystemTimeClock extends AnimationClock {
+
+ @Override
+ public long getTimeMillis() {
+ return SystemClock.uptimeMillis();
+ }
+ }
+}
diff --git a/src/com/android/camera/ui/motion/DampedSpring.java b/src/com/android/camera/ui/motion/DampedSpring.java
new file mode 100644
index 000000000..84cbfa6f8
--- /dev/null
+++ b/src/com/android/camera/ui/motion/DampedSpring.java
@@ -0,0 +1,145 @@
+/*
+ * 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.ui.motion;
+
+/**
+ * This models a value after the behavior of a spring. The value tracks the current value, a target
+ * value, and the current velocity and applies both a directional force and a damping force to the
+ * value on each update call.
+ */
+public class DampedSpring {
+ public static final float DEFAULT_TIME_TO_90_PERCENT_MILLIS = 200.0f;
+ public static final float DEFAULT_SPRING_STIFFNESS = 3.75f;
+ public static final float EPSILON = 0.01f;
+
+ private final float mSpringStiffness;
+ private final float mTimeTo90PercentMs;
+
+ private float mTarget = 0f;
+ private float mVelocity = 0f;
+ private float mValue = 0f;
+
+ public DampedSpring() {
+ this(DEFAULT_TIME_TO_90_PERCENT_MILLIS, DEFAULT_SPRING_STIFFNESS);
+ }
+
+ public DampedSpring(float timeTo90PercentMs) {
+ this(timeTo90PercentMs, DEFAULT_SPRING_STIFFNESS);
+ }
+
+ public DampedSpring(float timeTo90PercentMs, float springStiffness) {
+ // TODO: Assert timeTo90PercentMs >= 1ms, it might behave badly at low values.
+ // TODO: Assert springStiffness > 2.0f
+
+ mTimeTo90PercentMs = timeTo90PercentMs;
+ mSpringStiffness = springStiffness;
+
+ if (springStiffness > timeTo90PercentMs) {
+ throw new IllegalArgumentException("Creating a spring value with "
+ + "excessive stiffness will oscillate endlessly.");
+ }
+ }
+
+ /**
+ * @return the current value.
+ */
+ public float getValue() {
+ return mValue;
+ }
+
+ /**
+ * @param value the value to set this instance's current state too.
+ */
+ public void setValue(float value) {
+ mValue = value;
+ }
+
+ /**
+ * @return the current target value.
+ */
+ public float getTarget() {
+ return mTarget;
+ }
+
+ /**
+ * Set a target value. The current value will maintain any existing velocity values and will
+ * move towards the new target value. To forcibly stopAt the value use the stopAt() method.
+ *
+ * @param value the new value to move the current value towards.
+ */
+ public void setTarget(float value) {
+ mTarget = value;
+ }
+
+ /**
+ * Update the current value, moving it towards the actual value over the given
+ * time delta (in milliseconds) since the last update. This works off of the
+ * principle of a critically damped spring such that any given current value
+ * will move elastically towards the target value. The current value maintains
+ * and applies velocity, acceleration, and a damping force to give a continuous,
+ * smooth transition towards the target value.
+ *
+ * @param dtMs the time since the last update, or zero.
+ * @return the current value after the update occurs.
+ */
+ public float update(float dtMs) {
+ float dt = dtMs / mTimeTo90PercentMs;
+ float dts = dt * mSpringStiffness;
+
+ // If the dts > 1, and the velocity is zero, the force will exceed the
+ // distance to the target value and it will overshoot the value, causing
+ // weird behavior and unintended oscillation. since a critically damped
+ // spring should never overshoot the value, simply the current value to the
+ // target value.
+ if (dts > 1.0f || dts < 0.0f) {
+ stop();
+ return mValue;
+ }
+
+ float delta = (mTarget - mValue);
+ float force = delta - 2.0f * mVelocity;
+
+ mVelocity += force * dts;
+ mValue += mVelocity * dts;
+
+ // If we get close enough to the actual value, simply set the current value
+ // to the current target value and stop.
+ if (!isActive()) {
+ stop();
+ }
+
+ return mValue;
+ }
+
+ /**
+ * @return true if this instance has velocity or it is not at the target value.
+ */
+ public boolean isActive() {
+ boolean hasVelocity = Math.abs(mVelocity) >= EPSILON;
+ boolean atTarget = Math.abs(mTarget - mValue) < EPSILON;
+ return hasVelocity || !atTarget;
+ }
+
+ /**
+ * Stop the spring motion wherever it is currently at. Sets target to the
+ * current value and sets the velocity to zero.
+ */
+ public void stop() {
+ mTarget = mValue;
+ mVelocity = 0.0f;
+ }
+}
diff --git a/src/com/android/camera/ui/motion/DynamicAnimation.java b/src/com/android/camera/ui/motion/DynamicAnimation.java
new file mode 100644
index 000000000..57d5a1021
--- /dev/null
+++ b/src/com/android/camera/ui/motion/DynamicAnimation.java
@@ -0,0 +1,41 @@
+/*
+ * 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.ui.motion;
+
+import android.graphics.Canvas;
+
+/**
+ * Rendering object that can be driven by an animator instance.
+ */
+public interface DynamicAnimation {
+
+ /**
+ * Check to determine if this animation is currently in a stable state.
+ *
+ * @return true if the animation is stable, false if it should continue to be redrawn.
+ */
+ boolean isActive();
+
+ /**
+ * Update and draw the animation onto the given canvas.
+ *
+ * @param t current animation frame time.
+ * @param dt delta since the last update.
+ * @param canvas the canvas to draw the animation onto.
+ */
+ void draw(long t, long dt, Canvas canvas);
+}
diff --git a/src/com/android/camera/ui/motion/DynamicAnimator.java b/src/com/android/camera/ui/motion/DynamicAnimator.java
new file mode 100644
index 000000000..542ac1e37
--- /dev/null
+++ b/src/com/android/camera/ui/motion/DynamicAnimator.java
@@ -0,0 +1,116 @@
+/*
+ * 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.ui.motion;
+
+import android.graphics.Canvas;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Designed to handle the lifecycle of a view that needs a continuous update /
+ * redraw cycle that does not have a defined start / end time.
+ *
+ * Fixed length animations should NOT use this class.
+ */
+public class DynamicAnimator implements Invalidator {
+
+ public final List<DynamicAnimation> animations = new ArrayList<>();
+
+ private final Invalidator mInvalidator;
+ private final AnimationClock mClock;
+
+ private boolean mUpdateRequested = false;
+ private boolean mIsDrawing = false;
+ private long mLastDrawTimeMillis = 0;
+ private long mDrawTimeMillis = 0;
+
+ public DynamicAnimator(Invalidator invalidator, AnimationClock clock) {
+ mInvalidator = invalidator;
+ mClock = clock;
+ }
+
+ public void draw(Canvas canvas) {
+ mIsDrawing = true;
+ mUpdateRequested = false;
+
+ mDrawTimeMillis = mClock.getTimeMillis();
+
+ if (mLastDrawTimeMillis <= 0) {
+ mLastDrawTimeMillis = mDrawTimeMillis; // On the initial draw, dt is zero.
+ }
+
+ long dt = mDrawTimeMillis - mLastDrawTimeMillis;
+ mLastDrawTimeMillis = mDrawTimeMillis;
+
+ // Run the animation
+ for (DynamicAnimation renderer : animations) {
+ if (renderer.isActive()) {
+ renderer.draw(mDrawTimeMillis, dt, canvas);
+ }
+ }
+
+ // If either the update or the draw methods requested new frames, then
+ // invalidate the view which should give us another frame to work with.
+ // Otherwise, stopAt the last update time.
+ if (mUpdateRequested) {
+ mInvalidator.invalidate();
+ } else {
+ mLastDrawTimeMillis = -1;
+ }
+
+ mIsDrawing = false;
+ }
+
+ /**
+ * If a scheduleNewFrame request comes in outside of the animation loop,
+ * and we didn't schedule a frame after the previous loop (or it's the
+ * first time we've used this instance), invalidate the view and set the
+ * last update time to the current time. Theoretically, a few milliseconds
+ * have elapsed before the view gets updated.
+ */
+ @Override
+ public void invalidate() {
+ if (!mIsDrawing && !mUpdateRequested) {
+ mInvalidator.invalidate();
+ mLastDrawTimeMillis = mClock.getTimeMillis();
+ }
+
+ mUpdateRequested = true;
+ }
+
+ /**
+ * This will return the "best guess" for the most current animation frame
+ * time. If the loop is currently drawing, then it will return the time the
+ * draw began, and if an update is currently requested it will return the
+ * time that the update was requested at, and if neither of these are true
+ * it will return the current system clock time.
+ *
+ * This method will not trigger a new update.
+ */
+ public long getTimeMillis() {
+ if (mIsDrawing) {
+ return mDrawTimeMillis;
+ }
+
+ if (mUpdateRequested) {
+ return mLastDrawTimeMillis;
+ }
+
+ return mClock.getTimeMillis();
+ }
+}
diff --git a/src/com/android/camera/ui/motion/InterpolateUtils.java b/src/com/android/camera/ui/motion/InterpolateUtils.java
new file mode 100644
index 000000000..3c3cd532f
--- /dev/null
+++ b/src/com/android/camera/ui/motion/InterpolateUtils.java
@@ -0,0 +1,66 @@
+/*
+ * 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.ui.motion;
+
+/**
+ * Various static helper functions for interpolating between values.
+ */
+public class InterpolateUtils {
+
+ private InterpolateUtils() {
+ }
+
+ /**
+ * Linear interpolation from v0 to v1 as t goes from 0...1
+ *
+ * @param v0 the value at t=0
+ * @param v1 the value at t=1
+ * @param t value in the range of 0 to 1.
+ * @return the value between v0 and v1 as a ratio between 0 and 1 defined by t.
+ */
+ public static float lerp(float v0, float v1, float t) {
+ return v0 + t * (v1 - v0);
+ }
+
+ /**
+ * Project a value that is within the in(Min/Max) number space into the to(Min/Max) number
+ * space.
+ *
+ * @param v value to scale into the 'to' number space.
+ * @param vMin min value of the values number space.
+ * @param vMax max value of the values number space.
+ * @param pMin min value of the projection number space.
+ * @param pMax max value of the projection number space.
+ * @return the ratio of the value in the source number space as a value in the to(Min/Max)
+ * number space.
+ */
+ public static float scale(float v, float vMin, float vMax, float pMin, float pMax) {
+ return (pMax - pMin) * (v - vMin) / (vMax - vMin) + pMin;
+ }
+
+ /**
+ * Value between 0 and 1 as a ratio between tBegin over tDuration
+ * with no upper bound.
+ */
+ public static float unitRatio(long t, long tBegin, float tDuration) {
+ if (t <= tBegin) {
+ return 0.0f;
+ }
+
+ return (t - tBegin) / tDuration;
+ }
+}
diff --git a/src/com/android/camera/ui/motion/InterpolatorHelper.java b/src/com/android/camera/ui/motion/InterpolatorHelper.java
new file mode 100644
index 000000000..84114cb03
--- /dev/null
+++ b/src/com/android/camera/ui/motion/InterpolatorHelper.java
@@ -0,0 +1,38 @@
+/*
+ * 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.ui.motion;
+
+import android.content.Context;
+import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+
+import com.android.camera.util.ApiHelper;
+
+public class InterpolatorHelper {
+ private static Interpolator LINEAR_OUT_SLOW_IN = null;
+
+ public static Interpolator getLinearOutSlowInInterpolator(final Context context) {
+ if (LINEAR_OUT_SLOW_IN != null) {
+ return LINEAR_OUT_SLOW_IN;
+ }
+
+ LINEAR_OUT_SLOW_IN = AnimationUtils.loadInterpolator(
+ context, android.R.interpolator.linear_out_slow_in);
+ return LINEAR_OUT_SLOW_IN;
+ }
+}
diff --git a/src/com/android/camera/ui/motion/Invalidator.java b/src/com/android/camera/ui/motion/Invalidator.java
new file mode 100644
index 000000000..fdb548748
--- /dev/null
+++ b/src/com/android/camera/ui/motion/Invalidator.java
@@ -0,0 +1,28 @@
+/*
+ * 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.ui.motion;
+
+/**
+ * Basic interface for objects that can be invalidated.
+ */
+public interface Invalidator {
+ /**
+ * Request that the object should be redrawn whenever it gets
+ * the chance.
+ */
+ void invalidate();
+}
diff --git a/src/com/android/camera/ui/motion/LinearScale.java b/src/com/android/camera/ui/motion/LinearScale.java
new file mode 100644
index 000000000..5886f6882
--- /dev/null
+++ b/src/com/android/camera/ui/motion/LinearScale.java
@@ -0,0 +1,85 @@
+/*
+ * 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.ui.motion;
+
+/**
+ * Represents a discrete linear scale function.
+ */
+public final class LinearScale {
+ private final float mDomainA;
+ private final float mDomainB;
+ private final float mRangeA;
+ private final float mRangeB;
+
+ private final float mScale;
+
+ public LinearScale(float domainA, float domainB, float rangeA, float rangeB) {
+ mDomainA = domainA;
+ mDomainB = domainB;
+ mRangeA = rangeA;
+ mRangeB = rangeB;
+
+ // Precomputed ratio between input domain and output range.
+ float scale = (mRangeB - mRangeA) / (mDomainB - mDomainA);
+ mScale = Float.isNaN(scale) ? 0.0f : scale;
+ }
+
+ /**
+ * Clamp a given domain value to the given domain.
+ */
+ public float clamp(float domainValue) {
+ if (mDomainA > mDomainB) {
+ return Math.max(mDomainB, Math.min(mDomainA, domainValue));
+ }
+
+ return Math.max(mDomainA, Math.min(mDomainB, domainValue));
+ }
+
+ /**
+ * Returns true if the value is within the domain.
+ */
+ public boolean isInDomain(float domainValue) {
+ if (mDomainA > mDomainB) {
+ return domainValue <= mDomainA && domainValue >= mDomainB;
+ }
+ return domainValue >= mDomainA && domainValue <= mDomainB;
+ }
+
+ /**
+ * Linearly scale a given domain value into the output range.
+ */
+ public float scale(float domainValue) {
+ return mRangeA + (domainValue - mDomainA) * mScale;
+ }
+
+ /**
+ * For the current domain and range parameters produce a new scale function
+ * that is the inverse of the current scale function.
+ */
+ public LinearScale inverse() {
+ return new LinearScale(mRangeA, mRangeB, mDomainA, mDomainB);
+ }
+
+ @Override
+ public String toString() {
+ return "LinearScale{" +
+ "mDomainA=" + mDomainA +
+ ", mDomainB=" + mDomainB +
+ ", mRangeA=" + mRangeA +
+ ", mRangeB=" + mRangeB + "}";
+ }
+} \ No newline at end of file
diff --git a/src/com/android/camera/ui/motion/UnitBezier.java b/src/com/android/camera/ui/motion/UnitBezier.java
new file mode 100644
index 000000000..242f54556
--- /dev/null
+++ b/src/com/android/camera/ui/motion/UnitBezier.java
@@ -0,0 +1,157 @@
+/*
+ * 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.ui.motion;
+
+/**
+ * This represents is a precomputed cubic bezier curve starting at (0,0) and
+ * going to (1,1) with two configurable control points. Once the instance is
+ * created, the control points cannot be modified.
+ *
+ * Generally, this will be used for computing timing curves for with control
+ * points where an x value will be provide from 0.0 - 1.0, and the y value will
+ * be solved for where y is used as the timing value in some linear
+ * interpolation of a value.
+ */
+public class UnitBezier implements UnitCurve {
+
+ private static final float EPSILON = 1e-6f;
+
+ private final DerivableFloatFn mXFn;
+ private final DerivableFloatFn mYFn;
+
+ /**
+ * Build and pre-compute a unit bezier. This assumes a starting point of
+ * (0, 0) and end point of (1.0, 1.0).
+ *
+ * @param c0x control point x value for p0
+ * @param c0y control point y value for p0
+ * @param c1x control point x value for p1
+ * @param c1y control point y value for p1
+ */
+ public UnitBezier(float c0x, float c0y, float c1x, float c1y) {
+ mXFn = new CubicBezierFn(c0x, c1x);
+ mYFn = new CubicBezierFn(c0y, c1y);
+ }
+
+ /**
+ * Given a unit bezier curve find the height of the curve at t (which is
+ * internally represented as the xAxis).
+ *
+ * @param t the x position between 0 and 1 to solve for y.
+ * @return the closest approximate height of the curve at x.
+ */
+ @Override
+ public float valueAt(float t) {
+ return mYFn.value(solve(t, mXFn));
+ }
+
+ /**
+ * Given a unit bezier curve find a value along the x axis such that
+ * valueAt(result) produces the input value.
+ *
+ * @param value the y position between 0 and 1 to solve for x
+ * @return the closest approximate input that will produce value when provided
+ * to the valueAt function.
+ */
+ @Override
+ public float tAt(float value) {
+ return mXFn.value(solve(value, mYFn));
+ }
+
+ private float solve(float target, DerivableFloatFn fn) {
+ // For a linear fn, t = value. This makes value a good starting guess.
+ float input = target;
+
+ // Newton's method (Faster than bisection)
+ for (int i = 0; i < 8; i++) {
+ float value = fn.value(input) - target;
+ if (Math.abs(value) < EPSILON) {
+ return input;
+ }
+ float derivative = fn.derivative(input);
+ if (Math.abs(derivative) < EPSILON) {
+ break;
+ }
+ input = input - value / derivative;
+ }
+
+ // Fallback on bi-section
+ float min = 0.0f;
+ float max = 1.0f;
+ input = target;
+
+ if (input < min) {
+ return min;
+ }
+ if (input > max) {
+ return max;
+ }
+
+ while (min < max) {
+ float value = fn.value(input);
+ if (Math.abs(value - target) < EPSILON) {
+ return input;
+ }
+
+ if (target > value) {
+ min = input;
+ } else {
+ max = input;
+ }
+
+ input = (max - min) * .5f + min;
+ }
+
+ // Give up, return the closest match we got too.
+ return input;
+ }
+
+ private interface DerivableFloatFn {
+ float value(float x);
+ float derivative(float x);
+ }
+
+ /**
+ * Precomputed constants for a given set of control points along a given
+ * cubic bezier axis.
+ */
+ private static class CubicBezierFn implements DerivableFloatFn {
+ private final float c;
+ private final float a;
+ private final float b;
+
+ /**
+ * Build and pre-compute a single axis for a unit bezier. This assumes p0
+ * is 0 and p1 is 1.
+ *
+ * @param c0 start control point.
+ * @param c1 end control point.
+ */
+ public CubicBezierFn(float c0, float c1) {
+ c = 3.0f * c0;
+ b = 3.0f * (c1 - c0) - c;
+ a = 1.0f - c - b;
+ }
+
+ public float value(float x) {
+ return ((a * x + b) * x + c) * x;
+ }
+ public float derivative(float x) {
+ return (3.0f * a * x + 2.0f * b) * x + c;
+ }
+ }
+}
diff --git a/src/com/android/camera/ui/motion/UnitCurve.java b/src/com/android/camera/ui/motion/UnitCurve.java
new file mode 100644
index 000000000..d89f1fa4d
--- /dev/null
+++ b/src/com/android/camera/ui/motion/UnitCurve.java
@@ -0,0 +1,41 @@
+/*
+ * 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.ui.motion;
+
+/**
+ * Simple functions that produce values along a curve for any given input and can compute input
+ * times for a given output value.
+ */
+public interface UnitCurve {
+
+ /**
+ * Produce a unit value of this curve at time t. The function should always return a valid
+ * return value for any valid t input.
+ *
+ * @param t ratio of time passed from (0..1)
+ * @return the unit value at t.
+ */
+ float valueAt(float t);
+
+ /**
+ * If possible, find a value for t such that valueAt(t) == value or best guess.
+ *
+ * @param value to match to the output of valueAt(t)
+ * @return t where valueAt(t) == value or throw.
+ */
+ float tAt(float value);
+}
diff --git a/src/com/android/camera/ui/motion/UnitCurves.java b/src/com/android/camera/ui/motion/UnitCurves.java
new file mode 100644
index 000000000..a1117fa96
--- /dev/null
+++ b/src/com/android/camera/ui/motion/UnitCurves.java
@@ -0,0 +1,44 @@
+/*
+ * 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.ui.motion;
+
+/**
+ * Predefined material curves and animations.
+ */
+public class UnitCurves {
+ public static final UnitCurve FAST_OUT_SLOW_IN = new UnitBezier(0.4f, 0.0f, 0.2f, 1.0f);
+ public static final UnitCurve LINEAR_OUT_SLOW_IN = new UnitBezier(0.0f, 0.0f, 0.2f, 1.0f);
+ public static final UnitCurve FAST_OUT_LINEAR_IN = new UnitBezier(0.4f, 0.0f, 1.0f, 1.0f);
+ public static final UnitCurve LINEAR = new UnitBezier(0.0f, 0.0f, 1.0f, 1.0f);
+
+ /**
+ * Given two curves (from and to) and a time along the from curve, compute
+ * the time at t, and find a t along the 'toCurve' that will produce the
+ * same output. This is useful when interpolating between two different curves
+ * when the animation is not at the beginning or end.
+ *
+ * @param enterCurve the curve to compute the value from
+ * @param exitCurve the curve to find a time t on that matches output of
+ * enterCurve at T.
+ * @param t the time at which to compute the value (0..1)
+ * @return the time along the exitCurve.
+ */
+ public static float mapEnterCurveToExitCurveAtT(UnitCurve enterCurve, UnitCurve exitCurve,
+ float t) {
+ return exitCurve.tAt(1 - enterCurve.valueAt(t));
+ }
+}
diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java
index 34787e4d8..db86e753f 100755
--- a/src/com/android/camera/util/CameraUtil.java
+++ b/src/com/android/camera/util/CameraUtil.java
@@ -43,6 +43,7 @@ import android.net.Uri;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
@@ -70,6 +71,7 @@ import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
+import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
@@ -91,6 +93,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
+import java.util.TreeSet;
import static android.content.Context.MODE_PRIVATE;
@@ -109,7 +112,7 @@ public class CameraUtil {
public static final String KEY_SHOW_WHEN_LOCKED = "showWhenLocked";
// Orientation hysteresis amount used in rounding, in degrees
- public static final int ORIENTATION_HYSTERESIS = 5;
+ public static final int ORIENTATION_HYSTERESIS = 10;
public static final String REVIEW_ACTION = "com.android.camera.action.REVIEW";
// See android.hardware.Camera.ACTION_NEW_PICTURE.
@@ -133,6 +136,7 @@ public class CameraUtil {
public static final String SECURE_CAMERA_EXTRA = "secure_camera";
// Fields from android.hardware.Camera.Parameters
public static final String FOCUS_MODE_CONTINUOUS_PICTURE = "continuous-picture";
+ public static final String FOCUS_MODE_MW_CONTINUOUS_PICTURE = "mw_continuous-picture";
public static final String RECORDING_HINT = "recording-hint";
private static final String AUTO_EXPOSURE_LOCK_SUPPORTED = "auto-exposure-lock-supported";
private static final String AUTO_WHITE_BALANCE_LOCK_SUPPORTED = "auto-whitebalance-lock-supported";
@@ -142,6 +146,9 @@ public class CameraUtil {
public static final String TRUE = "true";
public static final String FALSE = "false";
+ // Hardware camera key mask
+ private static final int KEY_MASK_CAMERA = 0x20;
+
private static final Class<?>[] CTOR_SIGNATURE =
new Class[] {CaptureRequest.class, CameraMetadataNative.class, boolean.class, int.class};
@@ -181,6 +188,7 @@ public class CameraUtil {
}
public static boolean isVideoSnapshotSupported(Parameters params) {
+ if (params == null) return false;
return TRUE.equals(params.get(VIDEO_SNAPSHOT_SUPPORTED));
}
@@ -189,6 +197,10 @@ public class CameraUtil {
return (supported != null) && supported.contains(SCENE_MODE_HDR);
}
+ public static boolean hasCameraKey() {
+ return (sDeviceKeysPresent & KEY_MASK_CAMERA) != 0;
+ }
+
public static boolean isMeteringAreaSupported(Parameters params) {
return params.getMaxNumMeteringAreas() > 0;
}
@@ -199,6 +211,22 @@ public class CameraUtil {
params.getSupportedFocusModes()));
}
+ public static boolean isSupported(Parameters params, String key) {
+ return (params.get(key) != null && !"null".equals(params.get(key)));
+ }
+
+ public static int getNumSnapsPerShutter(Parameters params) {
+ String numJpegs = params.get("num-jpegs-per-shutter");
+ if (!TextUtils.isEmpty(numJpegs)) {
+ return Integer.valueOf(numJpegs);
+ }
+ String numSnaps = params.get("num-snaps-per-shutter");
+ if (!TextUtils.isEmpty(numSnaps)) {
+ return Integer.valueOf(numSnaps);
+ }
+ return 1;
+ }
+
// Private intent extras. Test only.
private static final String EXTRAS_CAMERA_FACING =
"android.intent.extras.CAMERA_FACING";
@@ -206,6 +234,9 @@ public class CameraUtil {
private static float sPixelDensity = 1;
private static ImageFileNamer sImageFileNamer;
+ // Get available hardware keys
+ private static int sDeviceKeysPresent;
+
private CameraUtil() {
}
@@ -217,6 +248,8 @@ public class CameraUtil {
sPixelDensity = metrics.density;
sImageFileNamer = new ImageFileNamer(
context.getString(R.string.image_file_name_format));
+ sDeviceKeysPresent = context.getResources().getInteger(
+ org.lineageos.platform.internal.R.integer.config_deviceHardwareKeys);
}
public static int dpToPixel(int dp) {
@@ -377,6 +410,37 @@ public class CameraUtil {
}
}
+ public static boolean isCamera2Supported(Context context) {
+ android.hardware.camera2.CameraManager manager = (android.hardware.camera2.CameraManager)
+ context.getSystemService(Context.CAMERA_SERVICE);
+
+ try {
+ String[] cameraIds = manager.getCameraIdList();
+
+ if (cameraIds != null && cameraIds.length > 0) {
+ CameraCharacteristics characteristics =
+ manager.getCameraCharacteristics(cameraIds[0]);
+ int deviceLevel =
+ characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
+
+ switch (deviceLevel) {
+ case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED:
+ return true;
+ case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL:
+ return true;
+ case CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3:
+ return true;
+ default:
+ return false;
+ }
+ }
+ } catch(CameraAccessException | NumberFormatException e) {
+ Log.e(TAG, "exception trying to get camera characteristics");
+ }
+
+ return false;
+ }
+
public static CameraManager.CameraProxy openCamera(
Activity activity, final int cameraId,
Handler handler, final CameraManager.CameraOpenErrorCallback cb) {
@@ -464,6 +528,11 @@ public class CameraUtil {
return 0;
}
+ public static boolean isScreenRotated(Activity activity) {
+ int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+ return rotation != Surface.ROTATION_0 && rotation != Surface.ROTATION_180;
+ }
+
/**
* Calculate the default orientation of the device based on the width and
* height of the display when rotation = 0 (i.e. natural width and height)
@@ -514,7 +583,7 @@ public class CameraUtil {
} else {
int dist = Math.abs(orientation - orientationHistory);
dist = Math.min( dist, 360 - dist );
- changeOrientation = ( dist >= 45 + ORIENTATION_HYSTERESIS );
+ changeOrientation = ( dist >= 60 + ORIENTATION_HYSTERESIS );
}
if (changeOrientation) {
return ((orientation + 45) / 90 * 90) % 360;
@@ -578,7 +647,7 @@ public class CameraUtil {
// TODO(andyhuibers): Don't hardcode this but use device's measurements.
final int MAX_ASPECT_HEIGHT = 1080;
// Use a very small tolerance because we want an exact match.
- final double ASPECT_TOLERANCE = 0.01;
+ final double ASPECT_TOLERANCE = 0.02;
if (sizes == null) return -1;
int optimalSizeIndex = -1;
@@ -762,13 +831,25 @@ public class CameraUtil {
return optimalSize;
}
- public static void dumpParameters(Parameters parameters) {
- String flattened = parameters.flatten();
- StringTokenizer tokenizer = new StringTokenizer(flattened, ";");
- Log.d(TAG, "Dump all camera parameters:");
- while (tokenizer.hasMoreElements()) {
- Log.d(TAG, tokenizer.nextToken());
+ public static void dumpParameters(Parameters params) {
+ Set<String> sortedParams = new TreeSet<String>();
+ sortedParams.addAll(Arrays.asList(params.flatten().split(";")));
+ StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ Iterator<String> i = sortedParams.iterator();
+ while (i.hasNext()) {
+ String nextParam = i.next();
+ if ((sb.length() + nextParam.length()) > 2044) {
+ Log.d(TAG, "Parameters: " + sb.toString());
+ sb = new StringBuilder();
+ }
+ sb.append(nextParam);
+ if (i.hasNext()) {
+ sb.append(", ");
+ }
}
+ sb.append("]");
+ Log.d(TAG, "Parameters: " + sb.toString());
}
/**
@@ -871,7 +952,7 @@ public class CameraUtil {
+ "," + rect.right + "," + rect.bottom + ")");
}
- public static void rectFToRect(RectF rectF, Rect rect) {
+ public static void inlineRectToRectF(RectF rectF, Rect rect) {
rect.left = Math.round(rectF.left);
rect.top = Math.round(rectF.top);
rect.right = Math.round(rectF.right);
@@ -880,7 +961,7 @@ public class CameraUtil {
public static Rect rectFToRect(RectF rectF) {
Rect rect = new Rect();
- rectFToRect(rectF, rect);
+ inlineRectToRectF(rectF, rect);
return rect;
}
@@ -900,21 +981,6 @@ public class CameraUtil {
matrix.postTranslate(viewWidth / 2f, viewHeight / 2f);
}
- public static void prepareMatrix(Matrix matrix, boolean mirror, int displayOrientation,
- Rect previewRect) {
- // Need mirror for front camera.
- matrix.setScale(mirror ? -1 : 1, 1);
- // This is the value for android.hardware.Camera.setDisplayOrientation.
- matrix.postRotate(displayOrientation);
-
- // Camera driver coordinates range from (-1000, -1000) to (1000, 1000).
- // We need to map camera driver coordinates to preview rect coordinates
- Matrix mapping = new Matrix();
- mapping.setRectToRect(new RectF(-1000, -1000, 1000, 1000), rectToRectF(previewRect),
- Matrix.ScaleToFit.FILL);
- matrix.setConcat(mapping, matrix);
- }
-
public static String createJpegName(long dateTaken, boolean refocus) {
synchronized (sImageFileNamer) {
return sImageFileNamer.generateName(dateTaken, refocus);
@@ -1057,6 +1123,20 @@ public class CameraUtil {
}
}
}
+
+ public static boolean isLowLuminance(Parameters parameters) {
+ String lC = parameters.get(CameraSettings.KEY_LUMINANCE_CONDITION);
+
+ if (lC != null) {
+ if (lC.equals(CameraSettings.LUMINANCE_CONDITION_LOW)) {
+ Log.d(TAG, "Parameter " + CameraSettings.KEY_LUMINANCE_CONDITION +
+ "=" + CameraSettings.LUMINANCE_CONDITION_LOW);
+ return true;
+ }
+ }
+ return false;
+ }
+
public static String getFilpModeString(int value){
switch(value){
case 0:
@@ -1132,6 +1212,15 @@ public class CameraUtil {
return new int[0];
}
+ public static int getMaxPreviewFps(Parameters params) {
+ List<Integer> frameRates = params.getSupportedPreviewFrameRates();
+ if (frameRates != null && frameRates.size() > 0) {
+ // The list is sorted. Return the last element.
+ return frameRates.get(frameRates.size() - 1).intValue();
+ }
+ return -1;
+ }
+
private static class ImageFileNamer {
private final SimpleDateFormat mFormat;
@@ -1259,10 +1348,6 @@ public class CameraUtil {
return ret;
}
- public static boolean volumeKeyShutterDisable(Context context) {
- return context.getResources().getBoolean(R.bool.volume_key_shutter_disable);
- }
-
public static int determineRatio(int width, int height) {
if (height != 0) {
return determineRatio(((float) width) / height);
diff --git a/src/com/android/camera/util/MultiMap.java b/src/com/android/camera/util/MultiMap.java
new file mode 100644
index 000000000..b2e9003fe
--- /dev/null
+++ b/src/com/android/camera/util/MultiMap.java
@@ -0,0 +1,45 @@
+package com.android.camera.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class MultiMap<K,V> {
+ Map<K,List<V>> map = new HashMap<K,List<V>>();
+
+ public void put(K key, V value) {
+ List<V> l = map.get(key);
+ if(l == null) {
+ l = new ArrayList<V>();
+ map.put(key, l);
+ }
+ l.add(value);
+ }
+
+ public List<V> get(K key) {
+ List<V> l = map.get(key);
+ if(l == null) { return Collections.emptyList(); }
+ else return l;
+ }
+
+ public List<V> remove(K key) {
+ List<V> l = map.remove(key);
+ if(l == null) { return Collections.emptyList(); }
+ else return l;
+ }
+
+ public Set<K> keySet() { return map.keySet(); }
+
+ public int size() {
+ int total = 0;
+ for(List<V> l : map.values()) {
+ total += l.size();
+ }
+ return total;
+ }
+
+ public boolean isEmpty() { return map.isEmpty(); }
+} \ No newline at end of file
diff --git a/src/com/android/camera/util/PersistUtil.java b/src/com/android/camera/util/PersistUtil.java
index 32b76d1e9..baba03cfa 100644
--- a/src/com/android/camera/util/PersistUtil.java
+++ b/src/com/android/camera/util/PersistUtil.java
@@ -52,8 +52,6 @@ public class PersistUtil {
SystemProperties.get("persist.sys.camera.preview.size", "");
private static final String PERSIST_CAMERA_VIDEO_SIZE =
SystemProperties.get("persist.sys.camera.video.size", "");
- private static final boolean PERSIST_CAMERA_CAMERA2 =
- SystemProperties.getBoolean("persist.sys.camera.camera2", true);
private static final boolean PERSIST_CAMERA_ZSL =
SystemProperties.getBoolean("persist.sys.camera.zsl.disabled", false);
private static final int PERSIST_CAMERA_CANCEL_TOUCHFOCUS_DELAY =
@@ -163,10 +161,6 @@ public class PersistUtil {
return result;
}
- public static boolean getCamera2Mode() {
- return PERSIST_CAMERA_CAMERA2;
- }
-
public static boolean getCameraZSLDisabled() {
return PERSIST_CAMERA_ZSL;
}
diff --git a/src/com/android/camera/util/VendorTagUtil.java b/src/com/android/camera/util/VendorTagUtil.java
index b2efbfa54..0cc6359ec 100755
--- a/src/com/android/camera/util/VendorTagUtil.java
+++ b/src/com/android/camera/util/VendorTagUtil.java
@@ -71,7 +71,7 @@ public class VendorTagUtil {
private static final int MANUAL_WB_CCT_MODE = 1;
private static final int MANUAL_WB_GAINS_MODE = 2;
- private static boolean isSupported(CaptureRequest.Builder builder,
+ public static boolean isSupported(CaptureRequest.Builder builder,
CaptureRequest.Key<?> key) {
boolean supported = true;
try {