Merge "new colors for GAR contrast compliance" into ub-camera-glacier
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index af9af0f..314840f 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -280,23 +280,17 @@
return mModuleManager;
}
- // close activity when screen turns off
- private final BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
+ /**
+ * Close activity when secure app passes lock screen or screen turns
+ * off.
+ */
+ private final BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
finish();
}
};
- private final ActionBar.OnMenuVisibilityListener mOnMenuVisibilityListener =
- new ActionBar.OnMenuVisibilityListener() {
- @Override
- public void onMenuVisibilityChanged(boolean isVisible) {
- // TODO: Remove this or bring back the original implementation: cancel
- // auto-hide actionbar.
- }
- };
-
/**
* Whether the screen is kept turned on.
*/
@@ -1320,6 +1314,10 @@
}
}
+ /**
+ * Note: Make sure this callback is unregistered properly when the activity
+ * is destroyed since we're otherwise leaking the Activity reference.
+ */
private final CameraExceptionHandler.CameraExceptionCallback mCameraExceptionCallback
= new CameraExceptionHandler.CameraExceptionCallback() {
@Override
@@ -1369,14 +1367,15 @@
@Override
public void onCreateTasks(Bundle state) {
CameraPerformanceTracker.onEvent(CameraPerformanceTracker.ACTIVITY_START);
+ mAppContext = getApplication().getBaseContext();
+
if (!Glide.isSetup()) {
- Glide.setup(new GlideBuilder(this)
+ Glide.setup(new GlideBuilder(getAndroidContext())
.setResizeService(new FifoPriorityThreadPoolExecutor(2)));
- Glide.get(this).setMemoryCategory(MemoryCategory.HIGH);
+ Glide.get(getAndroidContext()).setMemoryCategory(MemoryCategory.HIGH);
}
mOnCreateTime = System.currentTimeMillis();
- mAppContext = getApplicationContext();
mSoundPlayer = new SoundPlayer(mAppContext);
try {
@@ -1408,12 +1407,13 @@
} else {
mActionBar.setBackgroundDrawable(new ColorDrawable(0x80000000));
}
- mActionBar.addOnMenuVisibilityListener(mOnMenuVisibilityListener);
mMainHandler = new MainHandler(this, getMainLooper());
mCameraController = new CameraController(mAppContext, this, mMainHandler,
- CameraAgentFactory.getAndroidCameraAgent(this, CameraAgentFactory.CameraApi.API_1),
- CameraAgentFactory.getAndroidCameraAgent(this, CameraAgentFactory.CameraApi.AUTO));
+ CameraAgentFactory.getAndroidCameraAgent(mAppContext,
+ CameraAgentFactory.CameraApi.API_1),
+ CameraAgentFactory.getAndroidCameraAgent(mAppContext,
+ CameraAgentFactory.CameraApi.AUTO));
mCameraController.setCameraExceptionHandler(
new CameraExceptionHandler(mCameraExceptionCallback, mMainHandler));
@@ -1450,10 +1450,17 @@
win.setAttributes(params);
// Filter for screen off so that we can finish secure camera
- // activity
- // when screen is off.
- IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
- registerReceiver(mScreenOffReceiver, filter);
+ // activity when screen is off.
+ IntentFilter filter_screen_off = new IntentFilter(Intent.ACTION_SCREEN_OFF);
+ registerReceiver(mShutdownReceiver, filter_screen_off);
+
+ // Filter for phone unlock so that we can finish secure camera
+ // via this UI path:
+ // 1. from secure lock screen, user starts secure camera
+ // 2. user presses home button
+ // 3. user unlocks phone
+ IntentFilter filter_user_unlock = new IntentFilter(Intent.ACTION_USER_PRESENT);
+ registerReceiver(mShutdownReceiver, filter_user_unlock);
}
mCameraAppUI = new CameraAppUI(this,
(MainActivityLayout) findViewById(R.id.activity_root_view), isCaptureIntent());
@@ -1784,7 +1791,8 @@
mOrientationManager.resume();
mPeekAnimationThread = new HandlerThread("Peek animation");
mPeekAnimationThread.start();
- mPeekAnimationHandler = new PeekAnimationHandler(mPeekAnimationThread.getLooper());
+ mPeekAnimationHandler = new PeekAnimationHandler(mPeekAnimationThread.getLooper(),
+ mMainHandler, mAboveFilmstripControlLayout);
mCurrentModule.hardResetSettings(mSettingsManager);
mCurrentModule.resume();
@@ -1904,11 +1912,11 @@
@Override
public void onDestroyTasks() {
if (mSecureCamera) {
- unregisterReceiver(mScreenOffReceiver);
+ unregisterReceiver(mShutdownReceiver);
}
- mActionBar.removeOnMenuVisibilityListener(mOnMenuVisibilityListener);
mSettingsManager.removeAllListeners();
mCameraController.removeCallbackReceiver();
+ mCameraController.setCameraExceptionHandler(null);
getContentResolver().unregisterContentObserver(mLocalImagesObserver);
getContentResolver().unregisterContentObserver(mLocalVideosObserver);
getServices().getCaptureSessionManager().removeSessionListener(mSessionListener);
@@ -2465,6 +2473,11 @@
@Override
public void onOrientationChanged(int orientation) {
+ if (orientation != mLastRawOrientation) {
+ Log.v(TAG, "orientation changed (from:to) " + mLastRawOrientation +
+ ":" + orientation);
+ }
+
// We keep the last known orientation. So if the user first orient
// the camera then point the camera to floor or sky, we still have
// the correct orientation.
@@ -2701,7 +2714,7 @@
filmstripBottomPanel.setViewerButtonVisibility(viewButtonVisibility);
}
- private class PeekAnimationHandler extends Handler {
+ private static class PeekAnimationHandler extends Handler {
private class DataAndCallback {
LocalData mData;
com.android.camera.util.Callback<Bitmap> mCallback;
@@ -2713,8 +2726,14 @@
}
}
- public PeekAnimationHandler(Looper looper) {
+ private final Handler mMainHandler;
+ private final FrameLayout mAboveFilmstripControlLayout;
+
+ public PeekAnimationHandler(Looper looper, Handler mainHandler,
+ FrameLayout aboveFilmstripControlLayout) {
super(looper);
+ mMainHandler = mainHandler;
+ mAboveFilmstripControlLayout = aboveFilmstripControlLayout;
}
/**
diff --git a/src/com/android/camera/FocusOverlayManager.java b/src/com/android/camera/FocusOverlayManager.java
index 1c5e00a..4e4d54c 100644
--- a/src/com/android/camera/FocusOverlayManager.java
+++ b/src/com/android/camera/FocusOverlayManager.java
@@ -38,6 +38,7 @@
import com.android.camera.util.UsageStatistics;
import com.android.ex.camera2.portability.CameraCapabilities;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -133,17 +134,33 @@
public void setFocusParameters();
}
- private class MainHandler extends Handler {
- public MainHandler(Looper looper) {
+ /**
+ * TODO: Refactor this so that we either don't need a handler or make
+ * mListener not be the activity.
+ */
+ private static class MainHandler extends Handler {
+ /**
+ * The outer mListener at the moment is actually the CameraActivity,
+ * which we would leak if we didn't break the GC path here using a
+ * WeakReference.
+ */
+ final WeakReference<FocusOverlayManager> mManager;
+ public MainHandler(FocusOverlayManager manager, Looper looper) {
super(looper);
+ mManager = new WeakReference<FocusOverlayManager>(manager);
}
@Override
public void handleMessage(Message msg) {
+ FocusOverlayManager manager = mManager.get();
+ if (manager == null) {
+ return;
+ }
+
switch (msg.what) {
case RESET_TOUCH_FOCUS: {
- cancelAutoFocus();
- mListener.startFaceDetection();
+ manager.cancelAutoFocus();
+ manager.mListener.startFaceDetection();
break;
}
}
@@ -155,7 +172,7 @@
Listener listener, boolean mirror, Looper looper, FocusUI ui) {
mAppController = appController;
mSettingsManager = appController.getSettingsManager();
- mHandler = new MainHandler(looper);
+ mHandler = new MainHandler(this, looper);
mMatrix = new Matrix();
mDefaultFocusModes = new ArrayList<CameraCapabilities.FocusMode>(defaultFocusModes);
updateCapabilities(capabilities);
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index 5634fd7..9e6299f 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -256,6 +256,9 @@
private final float[] mR = new float[16];
private int mHeading = -1;
+ /** Used to detect motion. We use this to release focus lock early. */
+ private MotionManager mMotionManager;
+
/** True if all the parameters needed to start preview is ready. */
private boolean mCameraPreviewParamsReady = false;
@@ -1302,6 +1305,10 @@
mJpegRotation = info.getJpegOrientation(orientation);
mCameraDevice.setJpegOrientation(mJpegRotation);
+ Log.v(TAG, "capture orientation (display:device:used:jpeg) " +
+ mDisplayOrientation + ":" + mOrientation + ":" +
+ orientation + ":" + mJpegRotation);
+
mCameraDevice.takePicture(mHandler,
new ShutterCallback(!animateBefore),
mRawPictureCallback, mPostViewPictureCallback,
@@ -1659,9 +1666,9 @@
new FocusOverlayManager(mAppController, defaultFocusModes,
mCameraCapabilities, this, mMirror, mActivity.getMainLooper(),
mUI.getFocusUI());
- MotionManager motionManager = getServices().getMotionManager();
- if (motionManager != null) {
- motionManager.addListener(mFocusManager);
+ mMotionManager = getServices().getMotionManager();
+ if (mMotionManager != null) {
+ mMotionManager.addListener(mFocusManager);
}
}
mAppController.addPreviewAreaSizeChangedListener(mFocusManager);
@@ -1715,6 +1722,11 @@
// Remove the messages and runnables in the queue.
mHandler.removeCallbacksAndMessages(null);
+ if (mMotionManager != null) {
+ mMotionManager.removeListener(mFocusManager);
+ mMotionManager = null;
+ }
+
closeCamera();
mActivity.enableKeepScreenOn(false);
mUI.onPause();
@@ -1882,6 +1894,9 @@
if (mCameraDevice != null) {
mCameraDevice.setDisplayOrientation(mDisplayRotation);
}
+ Log.v(TAG, "setDisplayOrientation (rotation:orientation:display) " +
+ mDisplayRotation + ":" + mDisplayOrientation + ":" +
+ mDisplayOrientation);
}
/** Only called by UI thread. */
diff --git a/src/com/android/camera/app/CameraAppUI.java b/src/com/android/camera/app/CameraAppUI.java
index ac77af7..2362e69 100644
--- a/src/com/android/camera/app/CameraAppUI.java
+++ b/src/com/android/camera/app/CameraAppUI.java
@@ -1875,7 +1875,9 @@
boolean flashBackCamera = mController.getSettingsManager().getBoolean(
SettingsManager.SCOPE_GLOBAL, Keys.KEY_FLASH_SUPPORTED_BACK_CAMERA);
if (bottomBarSpec.hideFlash || !flashBackCamera) {
+ // Hide both flash and torch button in flash disable logic
buttonManager.hideButton(ButtonManager.BUTTON_FLASH);
+ buttonManager.hideButton(ButtonManager.BUTTON_TORCH);
} else {
if (hardwareSpec.isFlashSupported()) {
if (bottomBarSpec.enableFlash) {
@@ -1888,11 +1890,15 @@
buttonManager.initializeButton(ButtonManager.BUTTON_HDR_PLUS_FLASH,
bottomBarSpec.flashCallback);
} else {
+ // Hide both flash and torch button in flash disable logic
buttonManager.disableButton(ButtonManager.BUTTON_FLASH);
+ buttonManager.disableButton(ButtonManager.BUTTON_TORCH);
}
} else {
- // Disable flash icon if not supported by the hardware.
+ // Disable both flash and torch icon if not supported
+ // by the chosen camera hardware.
buttonManager.disableButton(ButtonManager.BUTTON_FLASH);
+ buttonManager.disableButton(ButtonManager.BUTTON_TORCH);
}
}
diff --git a/src/com/android/camera/one/OneCameraManager.java b/src/com/android/camera/one/OneCameraManager.java
index 7cd57ff..607e6a0 100644
--- a/src/com/android/camera/one/OneCameraManager.java
+++ b/src/com/android/camera/one/OneCameraManager.java
@@ -96,7 +96,7 @@
int maxMemoryMB = activity.getServices().getMemoryManager()
.getMaxAllowedNativeMemoryAllocation();
return new com.android.camera.one.v2.OneCameraManagerImpl(
- activity.getApplicationContext(), cameraManager, maxMemoryMB,
+ activity.getAndroidContext(), cameraManager, maxMemoryMB,
displayMetrics, activity.getSoundPlayer());
} else {
return new com.android.camera.one.v1.OneCameraManagerImpl();
diff --git a/src/com/android/camera/settings/CameraSettingsActivity.java b/src/com/android/camera/settings/CameraSettingsActivity.java
index db9c62c..82b54cd 100644
--- a/src/com/android/camera/settings/CameraSettingsActivity.java
+++ b/src/com/android/camera/settings/CameraSettingsActivity.java
@@ -254,6 +254,14 @@
* was found and removed.
*/
private boolean recursiveDelete(PreferenceGroup group, Preference preference) {
+ if (group == null) {
+ Log.d(TAG, "attempting to delete from null preference group");
+ return false;
+ }
+ if (preference == null) {
+ Log.d(TAG, "attempting to delete null preference");
+ return false;
+ }
if (group.removePreference(preference)) {
// Removal was successful.
return true;
diff --git a/src/com/android/camera/settings/SettingsUpgrader.java b/src/com/android/camera/settings/SettingsUpgrader.java
index 96797ac..4b38669 100644
--- a/src/com/android/camera/settings/SettingsUpgrader.java
+++ b/src/com/android/camera/settings/SettingsUpgrader.java
@@ -88,7 +88,12 @@
* modules to upgrade their boolean settings to Strings.
*/
protected boolean removeBoolean(SharedPreferences oldPreferencesLocation, String key) {
- boolean value = oldPreferencesLocation.getBoolean(key, false);
+ boolean value = false;
+ try {
+ value = oldPreferencesLocation.getBoolean(key, value);
+ } catch (ClassCastException e) {
+ Log.e(TAG, "error reading old value, removing and returning default", e);
+ }
oldPreferencesLocation.edit().remove(key).apply();
return value;
}
@@ -102,7 +107,12 @@
* modules to upgrade their Integer settings to Strings.
*/
protected int removeInteger(SharedPreferences oldPreferencesLocation, String key) {
- int value = oldPreferencesLocation.getInt(key, 0);
+ int value = 0;
+ try {
+ value = oldPreferencesLocation.getInt(key, value);
+ } catch (ClassCastException e) {
+ Log.e(TAG, "error reading old value, removing and returning default", e);
+ }
oldPreferencesLocation.edit().remove(key).apply();
return value;
}
@@ -116,7 +126,12 @@
* modules to upgrade their boolean settings to Strings.
*/
protected String removeString(SharedPreferences oldPreferencesLocation, String key) {
- String value = oldPreferencesLocation.getString(key, null);
+ String value = null;
+ try {
+ value = oldPreferencesLocation.getString(key, value);
+ } catch (ClassCastException e) {
+ Log.e(TAG, "error reading old value, removing and returning default", e);
+ }
oldPreferencesLocation.edit().remove(key).apply();
return value;
}
diff --git a/src/com/android/camera/widget/FilmstripView.java b/src/com/android/camera/widget/FilmstripView.java
index fbd0d03..70c2b86 100644
--- a/src/com/android/camera/widget/FilmstripView.java
+++ b/src/com/android/camera/widget/FilmstripView.java
@@ -813,7 +813,7 @@
data.prepare();
View recycled = getRecycledView(dataID);
- View v = mDataAdapter.getView(mActivity, recycled, dataID);
+ View v = mDataAdapter.getView(mActivity.getAndroidContext(), recycled, dataID);
if (v == null) {
return null;
}
@@ -1484,6 +1484,10 @@
getMeasuredWidth(), getMeasuredHeight());
final int offsetX = dim.x + mViewGapInPixel;
ViewItem viewItem = buildItemFromData(dataID);
+ if (viewItem == null) {
+ Log.w(TAG, "unable to build inserted item from data");
+ return;
+ }
if (insertedItemId >= mCurrentItem) {
if (insertedItemId == mCurrentItem) {
@@ -1898,7 +1902,7 @@
MyController(Context context) {
TimeInterpolator decelerateInterpolator = new DecelerateInterpolator(1.5f);
- mScroller = new MyScroller(mActivity,
+ mScroller = new MyScroller(mActivity.getAndroidContext(),
new Handler(mActivity.getMainLooper()),
mScrollerListener, decelerateInterpolator);
mCanStopScroll = true;
diff --git a/src/com/android/camera/widget/VideoRecordingHints.java b/src/com/android/camera/widget/VideoRecordingHints.java
index c931dfb..1c0b7a3 100644
--- a/src/com/android/camera/widget/VideoRecordingHints.java
+++ b/src/com/android/camera/widget/VideoRecordingHints.java
@@ -29,6 +29,8 @@
import com.android.camera.util.CameraUtil;
import com.android.camera2.R;
+import java.lang.ref.WeakReference;
+
/**
* This class is designed to show the video recording hint when device is held in
* portrait before video recording. The rotation device indicator will start rotating
@@ -58,6 +60,87 @@
private int mCenterY = UNSET;
private int mLastOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
+ private static class RotationAnimatorListener implements Animator.AnimatorListener {
+ private final WeakReference<VideoRecordingHints> mHints;
+ private boolean mCanceled = false;
+
+ public RotationAnimatorListener(VideoRecordingHints hint) {
+ mHints = new WeakReference<VideoRecordingHints>(hint);
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mCanceled = false;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ VideoRecordingHints hint = mHints.get();
+ if (hint == null) {
+ return;
+ }
+
+ hint.mRotation = ((int) hint.mRotation) % 360;
+ // If animation is canceled, do not restart it.
+ if (mCanceled) {
+ return;
+ }
+ hint.post(new Runnable() {
+ @Override
+ public void run() {
+ VideoRecordingHints hint = mHints.get();
+ if (hint != null) {
+ hint.continueRotationAnimation();
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCanceled = true;
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ // Do nothing.
+ }
+ }
+
+ private static class AlphaAnimatorListener implements Animator.AnimatorListener {
+ private final WeakReference<VideoRecordingHints> mHints;
+ AlphaAnimatorListener(VideoRecordingHints hint) {
+ mHints = new WeakReference<VideoRecordingHints>(hint);
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ // Do nothing.
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ VideoRecordingHints hint = mHints.get();
+ if (hint == null) {
+ return;
+ }
+
+ hint.invalidate();
+ hint.setAlpha(1f);
+ hint.mRotation = 0;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ // Do nothing.
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ // Do nothing.
+ }
+ }
+
public VideoRecordingHints(Context context, AttributeSet attrs) {
super(context, attrs);
mRotateArrows = getResources().getDrawable(R.drawable.rotate_arrows);
@@ -80,64 +163,11 @@
}
});
- mRotationAnimation.addListener(new Animator.AnimatorListener() {
- private boolean mCanceled = false;
- @Override
- public void onAnimationStart(Animator animation) {
- mCanceled = false;
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- mRotation = ((int) mRotation) % 360;
- // If animation is canceled, do not restart it.
- if (mCanceled) {
- return;
- }
- post(new Runnable() {
- @Override
- public void run() {
- continueRotationAnimation();
- }
- });
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mCanceled = true;
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- // Do nothing.
- }
- });
+ mRotationAnimation.addListener(new RotationAnimatorListener(this));
mAlphaAnimator = ObjectAnimator.ofFloat(this, "alpha", 1f, 0f);
mAlphaAnimator.setDuration(FADE_OUT_DURATION_MS);
- mAlphaAnimator.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- // Do nothing.
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- invalidate();
- setAlpha(1f);
- mRotation = 0;
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- // Do nothing.
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- // Do nothing.
- }
- });
+ mAlphaAnimator.addListener(new AlphaAnimatorListener(this));
mIsDefaultToPortrait = CameraUtil.isDefaultToPortrait(context);
}