OSDN Git Service

Merge "Fix for N4 Video Rotation Bug" into ub-camera-haleakala
[android-x86/packages-apps-Camera2.git] / src / com / android / camera / app / CameraAppUI.java
index 6e6be7c..3a7dac6 100644 (file)
@@ -16,7 +16,6 @@
 
 package com.android.camera.app;
 
-import android.accessibilityservice.AccessibilityServiceInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -32,9 +31,10 @@ import android.view.TextureView;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityManager;
 import android.widget.FrameLayout;
+import android.widget.ImageButton;
 
+import com.android.camera.AccessibilityUtil;
 import com.android.camera.AnimationManager;
 import com.android.camera.ButtonManager;
 import com.android.camera.CaptureLayoutHelper;
@@ -70,8 +70,6 @@ import com.android.camera.widget.ModeOptionsOverlay;
 import com.android.camera.widget.RoundedThumbnailView;
 import com.android.camera2.R;
 
-import java.util.List;
-
 /**
  * CameraAppUI centralizes control of views shared across modules. Whereas module
  * specific views will be handled in each Module UI. For example, we can now
@@ -354,8 +352,20 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
          */
         public boolean enablePanoOrientation;
 
+        /**
+         * Set true if manual exposure compensation should be visible.
+         *
+         * This option is not constrained by hardware limitations.
+         * For example, this is false in HDR+ mode.
+         */
         public boolean enableExposureCompensation;
 
+        /**
+         * Set true if the device and module support exposure compensation.
+         * Used only to show exposure button in disabled (greyed out) state.
+         */
+        public boolean isExposureCompensationSupported;
+
         /** Intent UI */
 
         /**
@@ -511,6 +521,7 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
     private TextureView mTextureView;
     private FrameLayout mModuleUI;
     private ShutterButton mShutterButton;
+    private ImageButton mCountdownCancelButton;
     private BottomBar mBottomBar;
     private ModeOptionsOverlay mModeOptionsOverlay;
     private IndicatorIconController mIndicatorIconController;
@@ -544,10 +555,13 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
     private View mModeOptionsToggle;
     private final RoundedThumbnailView mRoundedThumbnailView;
     private final CaptureLayoutHelper mCaptureLayoutHelper;
-    private boolean mAccessibilityEnabled;
     private final View mAccessibilityAffordances;
+    private AccessibilityUtil mAccessibilityUtil;
 
     private boolean mDisableAllUserInteractions;
+    /** Whether to prevent capture indicator from being triggered. */
+    private boolean mSuppressCaptureIndicator;
+
     /**
      * Provides current preview frame and the controls/overlay from the module that
      * are shown on top of the preview.
@@ -813,6 +827,8 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
                 showFilmstrip();
             }
         });
+
+        mSuppressCaptureIndicator = false;
     }
 
 
@@ -948,7 +964,7 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
                     mController.getQuickSwitchToModuleId(currentModuleIndex);
             if (currentModuleIndex != moduleToTransitionTo) {
                 mAppRootView.redirectTouchEventsTo(mModeTransitionView);
-                int shadeColorId = R.color.mode_cover_default_color;
+                int shadeColorId = R.color.camera_gray_background;
                 int iconRes = CameraUtil.getCameraModeCoverIconResId(moduleToTransitionTo,
                         mController.getAndroidContext());
 
@@ -991,21 +1007,9 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
 
         // Show UI that is meant to only be used when spoken feedback is
         // enabled.
-        mAccessibilityEnabled = isSpokenFeedbackAccessibilityEnabled();
         mAccessibilityAffordances.setVisibility(
-                (!mIsCaptureIntent && mAccessibilityEnabled) ? View.VISIBLE : View.GONE);
-    }
-
-    /**
-     * @return Whether any spoken feedback accessibility feature is currently
-     *         enabled.
-     */
-    private boolean isSpokenFeedbackAccessibilityEnabled() {
-        AccessibilityManager accessibilityManager = AndroidServices.instance()
-              .provideAccessibilityManager();
-        List<AccessibilityServiceInfo> infos = accessibilityManager
-                .getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN);
-        return infos != null && !infos.isEmpty();
+                (!mIsCaptureIntent && mAccessibilityUtil.isAccessibilityEnabled()) ? View.VISIBLE
+                        : View.GONE);
     }
 
     /**
@@ -1017,6 +1021,14 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
         mModeListView.onMenuPressed();
     }
 
+    public void showAccessibilityZoomUI(float maxZoom) {
+        mAccessibilityUtil.showZoomUI(maxZoom);
+    }
+
+    public void hideAccessibilityZoomUI() {
+        mAccessibilityUtil.hideZoomUI();
+    }
+
     /**
      * A cover view showing the mode theme color and mode icon will be visible on
      * top of preview until preview is ready (i.e. camera preview is started and
@@ -1024,7 +1036,7 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
      */
     private void showModeCoverUntilPreviewReady() {
         int modeId = mController.getCurrentModuleIndex();
-        int colorId = R.color.mode_cover_default_color;;
+        int colorId = R.color.camera_gray_background;;
         int iconId = CameraUtil.getCameraModeCoverIconResId(modeId, mController.getAndroidContext());
         mModeTransitionView.setupModeCover(colorId, iconId);
         mHideCoverRunnable = new Runnable() {
@@ -1064,7 +1076,7 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
             mAccessibilityAffordances.setVisibility(View.GONE);
         } else {
             setIndicatorBottomBarWrapperVisible(true);
-            if (!mIsCaptureIntent && mAccessibilityEnabled) {
+            if (!mIsCaptureIntent && mAccessibilityUtil.isAccessibilityEnabled()) {
                 mAccessibilityAffordances.setVisibility(View.VISIBLE);
             } else {
                 mAccessibilityAffordances.setVisibility(View.GONE);
@@ -1073,17 +1085,19 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
     }
 
     /**
-     * Call to stop the preview from being rendered.
+     * Call to stop the preview from being rendered. Sets the entire capture
+     * root view to invisible which includes the preview plus focus indicator
+     * and any other auxiliary views for capture modes.
      */
     public void pausePreviewRendering() {
-        mTextureView.setVisibility(View.INVISIBLE);
+        mCameraRootView.setVisibility(View.INVISIBLE);
     }
 
     /**
-     * Call to begin rendering the preview again.
+     * Call to begin rendering the preview and auxiliary views again.
      */
     public void resumePreviewRendering() {
-        mTextureView.setVisibility(View.VISIBLE);
+        mCameraRootView.setVisibility(View.VISIBLE);
     }
 
     /**
@@ -1104,6 +1118,28 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
 
     @Override
     public void onModeListOpenProgress(float progress) {
+        // When the mode list is in transition, ensure the large layers are
+        // hardware accelerated.
+        if (progress >= 1.0f || progress <= 0.0f) {
+            // Convert hardware layers back to default layer types when animation stops
+            // to prevent accidental artifacting.
+            if(mModeOptionsToggle.getLayerType() == View.LAYER_TYPE_HARDWARE ||
+                  mShutterButton.getLayerType() == View.LAYER_TYPE_HARDWARE) {
+                Log.v(TAG, "Disabling hardware layer for the Mode Options Toggle Button.");
+                mModeOptionsToggle.setLayerType(View.LAYER_TYPE_NONE, null);
+                Log.v(TAG, "Disabling hardware layer for the Shutter Button.");
+                mShutterButton.setLayerType(View.LAYER_TYPE_NONE, null);
+            }
+        } else {
+            if(mModeOptionsToggle.getLayerType() != View.LAYER_TYPE_HARDWARE ||
+                  mShutterButton.getLayerType() != View.LAYER_TYPE_HARDWARE) {
+                Log.v(TAG, "Enabling hardware layer for the Mode Options Toggle Button.");
+                mModeOptionsToggle.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                Log.v(TAG, "Enabling hardware layer for the Shutter Button.");
+                mShutterButton.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            }
+        }
+
         progress = 1 - progress;
         float interpolatedProgress = Gusterpolator.INSTANCE.getInterpolation(progress);
         mModeOptionsToggle.setAlpha(interpolatedProgress);
@@ -1116,6 +1152,16 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
 
     @Override
     public void onModeListClosed() {
+        // Convert hardware layers back to default layer types when animation stops
+        // to prevent accidental artifacting.
+        if(mModeOptionsToggle.getLayerType() == View.LAYER_TYPE_HARDWARE ||
+              mShutterButton.getLayerType() == View.LAYER_TYPE_HARDWARE) {
+            Log.v(TAG, "Disabling hardware layer for the Mode Options Toggle Button.");
+            mModeOptionsToggle.setLayerType(View.LAYER_TYPE_NONE, null);
+            Log.v(TAG, "Disabling hardware layer for the Shutter Button.");
+            mShutterButton.setLayerType(View.LAYER_TYPE_NONE, null);
+        }
+
         // Make sure the alpha on mode options ellipse is reset when mode drawer
         // is closed.
         mModeOptionsToggle.setAlpha(1f);
@@ -1180,7 +1226,13 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
     public void onChangeCamera() {
         ModuleController moduleController = mController.getCurrentModuleController();
         applyModuleSpecs(moduleController.getHardwareSpec(), moduleController.getBottomBarSpec());
+        syncModeOptionIndicators();
+    }
 
+    /**
+     * Updates the mode option indicators according to the current settings.
+     */
+    public void syncModeOptionIndicators() {
         if (mIndicatorIconController != null) {
             // Sync the settings state with the indicator state.
             mIndicatorIconController.syncIndicators();
@@ -1215,13 +1267,13 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
         mModuleUI = (FrameLayout) mCameraRootView.findViewById(R.id.module_layout);
         mTextureView = (TextureView) mCameraRootView.findViewById(R.id.preview_content);
         mTextureViewHelper = new TextureViewHelper(mTextureView, mCaptureLayoutHelper,
-                mController.getCameraProvider());
+                mController.getCameraProvider(), mController);
         mTextureViewHelper.setSurfaceTextureListener(this);
         mTextureViewHelper.setOnLayoutChangeListener(mPreviewLayoutChangeListener);
 
         mBottomBar = (BottomBar) mCameraRootView.findViewById(R.id.bottom_bar);
         int unpressedColor = mController.getAndroidContext().getResources()
-            .getColor(R.color.bottombar_unpressed);
+            .getColor(R.color.camera_gray_background);
         setBottomBarColor(unpressedColor);
         updateModeSpecificUIColors();
 
@@ -1246,6 +1298,7 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
         mPreviewOverlay = (PreviewOverlay) mCameraRootView.findViewById(R.id.preview_overlay);
         mPreviewOverlay.setOnTouchListener(new MyTouchListener());
         mPreviewOverlay.setOnPreviewTouchedListener(mModeOptionsOverlay);
+        mAccessibilityUtil = new AccessibilityUtil(mPreviewOverlay, mAccessibilityAffordances);
 
         mCaptureOverlay = (CaptureAnimationOverlay)
                 mCameraRootView.findViewById(R.id.capture_overlay);
@@ -1268,6 +1321,8 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
         mStickyBottomCaptureLayout = (StickyBottomCaptureLayout) mAppRootView
                 .findViewById(R.id.sticky_bottom_capture_layout);
         mStickyBottomCaptureLayout.setCaptureLayoutHelper(mCaptureLayoutHelper);
+        mCountdownCancelButton = (ImageButton) mStickyBottomCaptureLayout
+                .findViewById(R.id.shutter_cancel_button);
 
         mTextureViewHelper.addPreviewAreaSizeChangedListener(mModeListView);
         mTextureViewHelper.addAspectRatioChangedListener(
@@ -1481,12 +1536,19 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
        so that modules can have more knowledge of the status of the animation. */
 
     /**
+     * Turns on or off the capture indicator suppression.
+     */
+    public void setShouldSuppressCaptureIndicator(boolean suppress) {
+        mSuppressCaptureIndicator = suppress;
+    }
+
+    /**
      * Starts the capture indicator pop-out animation.
      *
      * @param accessibilityString An accessibility String to be announced during the peek animation.
      */
     public void startCaptureIndicatorRevealAnimation(String accessibilityString) {
-        if (mFilmstripLayout.getVisibility() == View.VISIBLE) {
+        if (mSuppressCaptureIndicator || mFilmstripLayout.getVisibility() == View.VISIBLE) {
             return;
         }
         mRoundedThumbnailView.startRevealThumbnailAnimation(accessibilityString);
@@ -1498,8 +1560,10 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
      * @param thumbnailBitmap The thumbnail image to be shown.
      */
     public void updateCaptureIndicatorThumbnail(Bitmap thumbnailBitmap, int rotation) {
-        mRoundedThumbnailView.setThumbnail(thumbnailBitmap);
-        mRoundedThumbnailView.setRotation(rotation);
+        if (mSuppressCaptureIndicator || mFilmstripLayout.getVisibility() == View.VISIBLE) {
+            return;
+        }
+        mRoundedThumbnailView.setThumbnail(thumbnailBitmap, rotation);
     }
 
     /**
@@ -1809,6 +1873,16 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
     }
 
     /**
+     * Sets or replaces the "cancel shutter" button listener.
+     * <p>
+     * TODO: Make this part of the interface the same way shutter button
+     * listeners are.
+     */
+    public void setCancelShutterButtonListener(View.OnClickListener listener) {
+        mCountdownCancelButton.setOnClickListener(listener);
+    }
+
+    /**
      * Performs a transition to the capture layout of the bottom bar.
      */
     public void transitionToCapture() {
@@ -1816,7 +1890,6 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
         applyModuleSpecs(moduleController.getHardwareSpec(),
             moduleController.getBottomBarSpec());
         mBottomBar.transitionToCapture();
-        showModeOptions();
     }
 
     /**
@@ -1827,7 +1900,6 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
         applyModuleSpecs(moduleController.getHardwareSpec(),
                 moduleController.getBottomBarSpec());
         mBottomBar.transitionToCancel();
-        hideModeOptions();
     }
 
     /**
@@ -1905,29 +1977,22 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
             buttonManager.hideButton(ButtonManager.BUTTON_CAMERA);
         }
 
-        if (bottomBarSpec.hideFlash) {
+        if (bottomBarSpec.hideFlash || !hardwareSpec.isFlashSupported()) {
             // 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) {
-                    buttonManager.initializeButton(ButtonManager.BUTTON_FLASH,
-                        bottomBarSpec.flashCallback);
-                } else if (bottomBarSpec.enableTorchFlash) {
-                    buttonManager.initializeButton(ButtonManager.BUTTON_TORCH,
-                        bottomBarSpec.flashCallback);
-                } else if (bottomBarSpec.enableHdrPlusFlash) {
-                    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);
-                }
+            if (bottomBarSpec.enableFlash) {
+                buttonManager.initializeButton(ButtonManager.BUTTON_FLASH,
+                    bottomBarSpec.flashCallback);
+            } else if (bottomBarSpec.enableTorchFlash) {
+                buttonManager.initializeButton(ButtonManager.BUTTON_TORCH,
+                    bottomBarSpec.flashCallback);
+            } else if (bottomBarSpec.enableHdrPlusFlash) {
+                buttonManager.initializeButton(ButtonManager.BUTTON_HDR_PLUS_FLASH,
+                    bottomBarSpec.flashCallback);
             } else {
-                // Disable both flash and torch icon if not supported
-                // by the chosen camera hardware.
+                // Disable both flash and torch button in flash disable logic
                 buttonManager.disableButton(ButtonManager.BUTTON_FLASH);
                 buttonManager.disableButton(ButtonManager.BUTTON_TORCH);
             }
@@ -1938,16 +2003,14 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
             buttonManager.hideButton(ButtonManager.BUTTON_HDR_PLUS);
         } else {
             if (hardwareSpec.isHdrPlusSupported()) {
-                if (bottomBarSpec.enableHdr && Keys.isCameraBackFacing(settingsManager,
-                                                                       mController.getModuleScope())) {
+                if (bottomBarSpec.enableHdr) {
                     buttonManager.initializeButton(ButtonManager.BUTTON_HDR_PLUS,
                             bottomBarSpec.hdrCallback);
                 } else {
                     buttonManager.disableButton(ButtonManager.BUTTON_HDR_PLUS);
                 }
             } else if (hardwareSpec.isHdrSupported()) {
-                if (bottomBarSpec.enableHdr && Keys.isCameraBackFacing(settingsManager,
-                                                                       mController.getModuleScope())) {
+                if (bottomBarSpec.enableHdr) {
                     buttonManager.initializeButton(ButtonManager.BUTTON_HDR,
                             bottomBarSpec.hdrCallback);
                 } else {
@@ -1990,20 +2053,37 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
             buttonManager.initializePanoOrientationButtons(bottomBarSpec.panoOrientationCallback);
         }
 
-        boolean enableExposureCompensation = bottomBarSpec.enableExposureCompensation &&
-            !(bottomBarSpec.minExposureCompensation == 0 && bottomBarSpec.maxExposureCompensation == 0) &&
-            mController.getSettingsManager().getBoolean(SettingsManager.SCOPE_GLOBAL,
-                        Keys.KEY_EXPOSURE_COMPENSATION_ENABLED);
-        if (enableExposureCompensation) {
-            buttonManager.initializePushButton(ButtonManager.BUTTON_EXPOSURE_COMPENSATION, null);
+
+
+        // If manual exposure is enabled both in SettingsManager and
+        // BottomBarSpec,then show the exposure button.
+        // If manual exposure is disabled in the BottomBarSpec (eg. HDR+
+        // enabled), but the device/module has the feature, then disable the exposure
+        // button.
+        // Otherwise, hide the button.
+        if (bottomBarSpec.enableExposureCompensation
+                && !(bottomBarSpec.minExposureCompensation == 0 && bottomBarSpec.maxExposureCompensation == 0)
+                && mController.getSettingsManager().getBoolean(SettingsManager.SCOPE_GLOBAL,
+                        Keys.KEY_EXPOSURE_COMPENSATION_ENABLED)) {
+            buttonManager.initializePushButton(ButtonManager.BUTTON_EXPOSURE_COMPENSATION,
+                    new View.OnClickListener() {
+                        @Override
+                        public void onClick(View v) {
+                            mModeOptionsOverlay.showExposureOptions();
+                        }
+                    });
             buttonManager.setExposureCompensationParameters(
-                bottomBarSpec.minExposureCompensation,
-                bottomBarSpec.maxExposureCompensation,
-                bottomBarSpec.exposureCompensationStep);
+                    bottomBarSpec.minExposureCompensation,
+                    bottomBarSpec.maxExposureCompensation,
+                    bottomBarSpec.exposureCompensationStep);
 
             buttonManager.setExposureCompensationCallback(
                     bottomBarSpec.exposureCompensationSetCallback);
             buttonManager.updateExposureButtons();
+        } else if (mController.getSettingsManager().getBoolean(SettingsManager.SCOPE_GLOBAL,
+                Keys.KEY_EXPOSURE_COMPENSATION_ENABLED)
+                && bottomBarSpec.isExposureCompensationSupported) {
+            buttonManager.disableButton(ButtonManager.BUTTON_EXPOSURE_COMPENSATION);
         } else {
             buttonManager.hideButton(ButtonManager.BUTTON_EXPOSURE_COMPENSATION);
             buttonManager.setExposureCompensationCallback(null);
@@ -2049,4 +2129,8 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
     public void hideFilmstrip() {
         mFilmstripLayout.hideFilmstrip();
     }
+
+    public int getFilmstripVisibility() {
+        return mFilmstripLayout.getVisibility();
+    }
 }