summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/util
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2015-03-24 07:23:19 -0700
committerSteve Kondik <steve@cyngn.com>2015-03-24 07:23:19 -0700
commit6eaafbef54de3a9b70ec338512b537cd0f7b5d13 (patch)
tree69646095b714fc45fb7c4d8aeeae6dcaf8aa3d49 /src/com/android/camera/util
parent708b6b29c2cde2510b6cee475bbb91f0ac06c74f (diff)
parent6cb15e279f0fcecfab919a51b6a542bcef5bd2f1 (diff)
downloadandroid_packages_apps_Camera2-staging/cm-12.1.tar.gz
android_packages_apps_Camera2-staging/cm-12.1.tar.bz2
android_packages_apps_Camera2-staging/cm-12.1.zip
Merge branch 'lollipop-mr1-release' of https://android.googlesource.com/platform/packages/apps/Camera2 into cm-12.1staging/cm-12.1
Change-Id: I24fa423d91d8d441cbf5d9e75b98037584dd2fbc
Diffstat (limited to 'src/com/android/camera/util')
-rw-r--r--src/com/android/camera/util/ApiHelper.java13
-rw-r--r--src/com/android/camera/util/CameraUtil.java42
-rw-r--r--src/com/android/camera/util/QuickActivity.java227
3 files changed, 276 insertions, 6 deletions
diff --git a/src/com/android/camera/util/ApiHelper.java b/src/com/android/camera/util/ApiHelper.java
index 713397588..7f6f59c8a 100644
--- a/src/com/android/camera/util/ApiHelper.java
+++ b/src/com/android/camera/util/ApiHelper.java
@@ -42,6 +42,7 @@ public class ApiHelper {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
public static final boolean HAS_CAMERA_HDR_PLUS = isKitKatOrHigher();
+ public static final boolean HDR_PLUS_CAN_USE_ARBITRARY_ASPECT_RATIOS = isKitKatMR2OrHigher();
public static final boolean HAS_CAMERA_HDR =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
public static final boolean HAS_DISPLAY_LISTENER =
@@ -59,6 +60,12 @@ public class ApiHelper {
&& "hammerhead".equalsIgnoreCase(Build.DEVICE);
public static final boolean IS_NEXUS_6 = "motorola".equalsIgnoreCase(Build.MANUFACTURER)
&& "shamu".equalsIgnoreCase(Build.DEVICE);
+ public static final boolean IS_NEXUS_9 = "htc".equalsIgnoreCase(Build.MANUFACTURER)
+ && ("flounder".equalsIgnoreCase(Build.DEVICE)
+ || "flounder_lte".equalsIgnoreCase(Build.DEVICE));
+ public static final boolean IS_HTC = "htc".equalsIgnoreCase(Build.MANUFACTURER);
+
+ public static final boolean HAS_CAMERA_2_API = isLOrHigher();
public static int getIntFieldIfExists(Class<?> klass, String fieldName,
Class<?> obj, int defaultVal) {
@@ -76,6 +83,12 @@ public class ApiHelper {
|| "KeyLimePie".equals(Build.VERSION.CODENAME);
}
+ public static boolean isKitKatMR2OrHigher() {
+ return isLOrHigher()
+ || (isKitKatOrHigher() &&
+ ("4.4.4".equals(Build.VERSION.RELEASE) || "4.4.3".equals(Build.VERSION.RELEASE)));
+ }
+
public static boolean isLOrHigher() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|| "L".equals(Build.VERSION.CODENAME);
diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java
index a55aa8451..d6237a92e 100644
--- a/src/com/android/camera/util/CameraUtil.java
+++ b/src/com/android/camera/util/CameraUtil.java
@@ -40,7 +40,6 @@ import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.telephony.TelephonyManager;
import android.util.DisplayMetrics;
-import android.util.FloatMath;
import android.util.TypedValue;
import android.view.Display;
import android.view.OrientationEventListener;
@@ -301,6 +300,7 @@ public class CameraUtil {
// appearing, so check to ensure that the activity is not shutting down
// before attempting to attach a dialog to the window manager.
if (!activity.isFinishing()) {
+ Log.e(TAG, "Show fatal error dialog");
new AlertDialog.Builder(activity)
.setCancelable(false)
.setTitle(R.string.camera_error_title)
@@ -513,7 +513,15 @@ public class CameraUtil {
public static int getOptimalPreviewSizeIndex(Context context,
List<Size> sizes, double targetRatio) {
// Use a very small tolerance because we want an exact match.
- final double ASPECT_TOLERANCE = 0.01;
+ final double ASPECT_TOLERANCE;
+ // HTC 4:3 ratios is over .01 from true 4:3, targeted fix for those
+ // devices here, see b/18241645
+ if (ApiHelper.IS_HTC && targetRatio > 1.3433 && targetRatio < 1.35) {
+ Log.w(TAG, "4:3 ratio out of normal tolerance, increasing tolerance to 0.02");
+ ASPECT_TOLERANCE = 0.02;
+ } else {
+ ASPECT_TOLERANCE = 0.01;
+ }
if (sizes == null) {
return -1;
}
@@ -552,7 +560,7 @@ public class CameraUtil {
// Cannot find the one match the aspect ratio. This should not happen.
// Ignore the requirement.
if (optimalSizeIndex == -1) {
- Log.w(TAG, "No preview size match the aspect ratio");
+ Log.w(TAG, "No preview size match the aspect ratio. available sizes: " + sizes);
minDiff = Double.MAX_VALUE;
for (int i = 0; i < sizes.size(); i++) {
Size size = sizes.get(i);
@@ -562,12 +570,24 @@ public class CameraUtil {
}
}
}
+
return optimalSizeIndex;
}
- /** Returns the largest picture size which matches the given aspect ratio. */
+ /**
+ * Returns the largest picture size which matches the given aspect ratio,
+ * except for the special WYSIWYG case where the picture size exactly matches
+ * the target size.
+ *
+ * @param sizes a list of candidate sizes, available for use
+ * @param targetWidth the ideal width of the video snapshot
+ * @param targetHeight the ideal height of the video snapshot
+ * @return the Optimal Video Snapshot Picture Size
+ */
public static com.android.ex.camera2.portability.Size getOptimalVideoSnapshotPictureSize(
- List<com.android.ex.camera2.portability.Size> sizes, double targetRatio) {
+ List<com.android.ex.camera2.portability.Size> sizes, int targetWidth,
+ int targetHeight) {
+
// Use a very small tolerance because we want an exact match.
final double ASPECT_TOLERANCE = 0.001;
if (sizes == null) {
@@ -576,7 +596,17 @@ public class CameraUtil {
com.android.ex.camera2.portability.Size optimalSize = null;
+ // WYSIWYG Override
+ // We assume that physical display constraints have already been
+ // imposed on the variables sizes
+ for (com.android.ex.camera2.portability.Size size : sizes) {
+ if (size.height() == targetHeight && size.width() == targetWidth) {
+ return size;
+ }
+ }
+
// Try to find a size matches aspect ratio and has the largest width
+ final double targetRatio = (double) targetWidth / targetHeight;
for (com.android.ex.camera2.portability.Size size : sizes) {
double ratio = (double) size.width() / size.height();
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) {
@@ -903,7 +933,7 @@ public class CameraUtil {
float sigma = len;
float sum = 0;
for (int i = 0; i <= mid; i++) {
- float ex = FloatMath.exp(-(i - mid) * (i - mid) / (mid * mid))
+ float ex = (float) Math.exp(-(i - mid) * (i - mid) / (mid * mid))
/ (2 * sigma * sigma);
int symmetricIndex = len - 1 - i;
mask[i] = ex;
diff --git a/src/com/android/camera/util/QuickActivity.java b/src/com/android/camera/util/QuickActivity.java
new file mode 100644
index 000000000..039d8fc9b
--- /dev/null
+++ b/src/com/android/camera/util/QuickActivity.java
@@ -0,0 +1,227 @@
+/*
+ * 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.util;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.provider.MediaStore;
+
+import com.android.camera.debug.Log;
+
+/**
+ * Workaround for secure-lockscreen double-onResume() bug:
+ * <p>
+ * If started from the secure-lockscreen, the activity may be quickly started,
+ * resumed, paused, stopped, and then started and resumed again. This is
+ * problematic for launch time from the secure-lockscreen because we typically open the
+ * camera in onResume() and close it in onPause(). These camera operations take
+ * a long time to complete. To workaround it, this class filters out
+ * high-frequency onResume()->onPause() sequences if the current intent
+ * indicates that we have started from the secure-lockscreen.
+ * </p>
+ * <p>
+ * Subclasses should override the appropriate on[Create|Start...]Tasks() method
+ * in place of the original.
+ * </p>
+ * <p>
+ * Sequences of onResume() followed quickly by onPause(), when the activity is
+ * started from a secure-lockscreen will result in a quick no-op.<br>
+ * </p>
+ */
+public abstract class QuickActivity extends Activity {
+ private static final Log.Tag TAG = new Log.Tag("QuickActivity");
+
+ /**
+ * The amount of time to wait before running onResumeTasks when started from
+ * the lockscreen.
+ */
+ private static final long ON_RESUME_DELAY_MILLIS = 20;
+ /** A reference to the main handler on which to run lifecycle methods. */
+ private Handler mMainHandler;
+ private boolean mPaused;
+ /**
+ * True if the last call to onResume() resulted in a delayed call to
+ * mOnResumeTasks which was then canceled due to an immediate onPause().
+ * This allows optimizing the common case in which the subsequent
+ * call to onResume() should execute onResumeTasks() immediately.
+ */
+ private boolean mCanceledResumeTasks = false;
+
+ /**
+ * A runnable for deferring tasks to be performed in onResume() if starting
+ * from the lockscreen.
+ */
+ private final Runnable mOnResumeTasks = new Runnable() {
+ @Override
+ public void run() {
+ logLifecycle("onResumeTasks", true);
+ if (mPaused) {
+ onResumeTasks();
+ mPaused = false;
+ mCanceledResumeTasks = false;
+ }
+ logLifecycle("onResumeTasks", false);
+ }
+ };
+
+ @Override
+ protected final void onNewIntent(Intent intent) {
+ logLifecycle("onNewIntent", true);
+ Log.v(TAG, "Intent Action = " + intent.getAction());
+ setIntent(intent);
+ super.onNewIntent(intent);
+ onNewIntentTasks(intent);
+ logLifecycle("onNewIntent", false);
+ }
+
+ @Override
+ protected final void onCreate(Bundle bundle) {
+ logLifecycle("onCreate", true);
+ Log.v(TAG, "Intent Action = " + getIntent().getAction());
+ super.onCreate(bundle);
+
+ mMainHandler = new Handler(getMainLooper());
+
+ onCreateTasks(bundle);
+
+ mPaused = true;
+
+ logLifecycle("onCreate", false);
+ }
+
+ @Override
+ protected final void onStart() {
+ logLifecycle("onStart", true);
+ onStartTasks();
+ super.onStart();
+ logLifecycle("onStart", false);
+ }
+
+ @Override
+ protected final void onResume() {
+ logLifecycle("onResume", true);
+ mMainHandler.removeCallbacks(mOnResumeTasks);
+ if (delayOnResumeOnStart() && !mCanceledResumeTasks) {
+ mMainHandler.postDelayed(mOnResumeTasks, ON_RESUME_DELAY_MILLIS);
+ } else {
+ if (mPaused) {
+ onResumeTasks();
+ mPaused = false;
+ mCanceledResumeTasks = false;
+ }
+ }
+ super.onResume();
+ logLifecycle("onResume", false);
+ }
+
+ @Override
+ protected final void onPause() {
+ logLifecycle("onPause", true);
+ mMainHandler.removeCallbacks(mOnResumeTasks);
+ if (!mPaused) {
+ onPauseTasks();
+ mPaused = true;
+ } else {
+ mCanceledResumeTasks = true;
+ }
+ super.onPause();
+ logLifecycle("onPause", false);
+ }
+
+ @Override
+ protected final void onStop() {
+ if (isChangingConfigurations()) {
+ Log.v(TAG, "changing configurations");
+ }
+ logLifecycle("onStop", true);
+ onStopTasks();
+ super.onStop();
+ logLifecycle("onStop", false);
+ }
+
+ @Override
+ protected final void onRestart() {
+ logLifecycle("onRestart", true);
+ super.onRestart();
+ // TODO Support onRestartTasks() and handle the workaround for that too.
+ logLifecycle("onRestart", false);
+ }
+
+ @Override
+ protected final void onDestroy() {
+ logLifecycle("onDestroy", true);
+ onDestroyTasks();
+ super.onDestroy();
+ logLifecycle("onDestroy", false);
+ }
+
+ private void logLifecycle(String methodName, boolean start) {
+ String prefix = start ? "START" : "END";
+ Log.v(TAG, prefix + " " + methodName + ": Activity = " + toString());
+ }
+
+ private boolean delayOnResumeOnStart() {
+ String action = getIntent().getAction();
+ boolean isSecureLockscreenCamera =
+ MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(action);
+ return isSecureLockscreenCamera;
+ }
+
+ /**
+ * Subclasses should override this in place of {@link Activity#onNewIntent}.
+ */
+ protected void onNewIntentTasks(Intent newIntent) {
+ }
+
+ /**
+ * Subclasses should override this in place of {@link Activity#onCreate}.
+ */
+ protected void onCreateTasks(Bundle savedInstanceState) {
+ }
+
+ /**
+ * Subclasses should override this in place of {@link Activity#onStart}.
+ */
+ protected void onStartTasks() {
+ }
+
+ /**
+ * Subclasses should override this in place of {@link Activity#onResume}.
+ */
+ protected void onResumeTasks() {
+ }
+
+ /**
+ * Subclasses should override this in place of {@link Activity#onPause}.
+ */
+ protected void onPauseTasks() {
+ }
+
+ /**
+ * Subclasses should override this in place of {@link Activity#onStop}.
+ */
+ protected void onStopTasks() {
+ }
+
+ /**
+ * Subclasses should override this in place of {@link Activity#onDestroy}.
+ */
+ protected void onDestroyTasks() {
+ }
+}