diff options
author | Steve Kondik <steve@cyngn.com> | 2015-03-24 07:23:19 -0700 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2015-03-24 07:23:19 -0700 |
commit | 6eaafbef54de3a9b70ec338512b537cd0f7b5d13 (patch) | |
tree | 69646095b714fc45fb7c4d8aeeae6dcaf8aa3d49 /src/com/android/camera/util | |
parent | 708b6b29c2cde2510b6cee475bbb91f0ac06c74f (diff) | |
parent | 6cb15e279f0fcecfab919a51b6a542bcef5bd2f1 (diff) | |
download | android_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.java | 13 | ||||
-rw-r--r-- | src/com/android/camera/util/CameraUtil.java | 42 | ||||
-rw-r--r-- | src/com/android/camera/util/QuickActivity.java | 227 |
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() { + } +} |