PhotoUI.java revision 5596b4c902dcb685928b43678f428746ca5ffd08
1d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb/*
26432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu * Copyright (C) 2012 The Android Open Source Project
3d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb *
4d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * Licensed under the Apache License, Version 2.0 (the "License");
5d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * you may not use this file except in compliance with the License.
6d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * You may obtain a copy of the License at
7d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb *
8d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb *      http://www.apache.org/licenses/LICENSE-2.0
9d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb *
10d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * Unless required by applicable law or agreed to in writing, software
11d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * distributed under the License is distributed on an "AS IS" BASIS,
12d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * See the License for the specific language governing permissions and
14d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * limitations under the License.
15d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb */
16d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
17d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbpackage com.android.camera;
18d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
196a83d528b09c55ade6ad44b82c81d4476ac57441Doris Liuimport android.app.AlertDialog;
2037f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberlingimport android.graphics.Bitmap;
216432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liuimport android.graphics.Matrix;
226432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liuimport android.graphics.SurfaceTexture;
23d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.hardware.Camera;
24d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.hardware.Camera.Face;
2537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberlingimport android.os.AsyncTask;
26f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liuimport android.view.GestureDetector;
27f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liuimport android.view.MotionEvent;
28d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.view.View;
29d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.view.ViewGroup;
30d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
31d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport com.android.camera.FocusOverlayManager.FocusUI;
3220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport com.android.camera.app.CameraManager;
335596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log;
34d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport com.android.camera.ui.FaceView;
35f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liuimport com.android.camera.ui.PreviewOverlay;
3606db742814dd635d100639f977fcfdc904deb778Doris Liuimport com.android.camera.ui.PreviewStatusListener;
37b50b5cbfbc0a67db6fc43373363b10381c9c61a3Angus Kongimport com.android.camera.util.CameraUtil;
388e963a5a6016d246184ed65906f9d103e92b17e2Sascha Haeberlingimport com.android.camera2.R;
39b50b5cbfbc0a67db6fc43373363b10381c9c61a3Angus Kong
40b50b5cbfbc0a67db6fc43373363b10381c9c61a3Angus Kongimport java.util.List;
41d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
42482de029dc20e0a577388a602985fb31c3200309Doris Liupublic class PhotoUI implements PreviewStatusListener,
439e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong    CameraManager.CameraFaceDetectionCallback {
44d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
455596b4c902dcb685928b43678f428746ca5ffd08Angus Kong    private static final Log.Tag TAG = new Log.Tag("PhotoUI");
4637f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    private static final int DOWN_SAMPLE_FACTOR = 4;
4770da918464276b110c43868caa272c97baadb89eDoris Liu    private static final float UNSET = 0f;
480f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague
49f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu    private final PreviewOverlay mPreviewOverlay;
50482de029dc20e0a577388a602985fb31c3200309Doris Liu    private final FocusUI mFocusUI;
51e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling    private final CameraActivity mActivity;
52e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling    private final PhotoController mController;
53d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
54e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling    private final View mRootView;
55d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
56d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu    // TODO: Remove face view logic if UX does not bring it back within a month.
57d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu    private FaceView mFaceView = null;
5836e56fba281292255a01ee00b4bee067fa09ab59Doris Liu    private DecodeImageForReview mDecodeTaskForReview = null;
59d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
60d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    private int mZoomMax;
61d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    private List<Integer> mZoomRatios;
62d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
63d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    private int mPreviewWidth = 0;
64d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    private int mPreviewHeight = 0;
6570da918464276b110c43868caa272c97baadb89eDoris Liu    private float mAspectRatio = UNSET;
660744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
6706db742814dd635d100639f977fcfdc904deb778Doris Liu    private final GestureDetector.OnGestureListener mPreviewGestureListener
6806db742814dd635d100639f977fcfdc904deb778Doris Liu            = new GestureDetector.SimpleOnGestureListener() {
6906db742814dd635d100639f977fcfdc904deb778Doris Liu        @Override
7006db742814dd635d100639f977fcfdc904deb778Doris Liu        public boolean onSingleTapUp(MotionEvent ev) {
7106db742814dd635d100639f977fcfdc904deb778Doris Liu            mController.onSingleTapUp(null, (int) ev.getX(), (int) ev.getY());
7206db742814dd635d100639f977fcfdc904deb778Doris Liu            return true;
7306db742814dd635d100639f977fcfdc904deb778Doris Liu        }
7406db742814dd635d100639f977fcfdc904deb778Doris Liu    };
750744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
7606db742814dd635d100639f977fcfdc904deb778Doris Liu    @Override
7706db742814dd635d100639f977fcfdc904deb778Doris Liu    public GestureDetector.OnGestureListener getGestureListener() {
7806db742814dd635d100639f977fcfdc904deb778Doris Liu        return mPreviewGestureListener;
7906db742814dd635d100639f977fcfdc904deb778Doris Liu    }
8006db742814dd635d100639f977fcfdc904deb778Doris Liu
814a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu    @Override
82d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren    public View.OnTouchListener getTouchListener() {
83d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren        return null;
84d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren    }
85d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren
86d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren    @Override
874a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu    public void onPreviewLayoutChanged(View v, int left, int top, int right,
884a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu            int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
894a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu        int width = right - left;
904a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu        int height = bottom - top;
914a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu        if (mPreviewWidth != width || mPreviewHeight != height) {
924a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu            mPreviewWidth = width;
934a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu            mPreviewHeight = height;
94d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        }
954a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu    }
96d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
9770da918464276b110c43868caa272c97baadb89eDoris Liu    @Override
9870da918464276b110c43868caa272c97baadb89eDoris Liu    public boolean shouldAutoAdjustTransformMatrixOnLayout() {
9970da918464276b110c43868caa272c97baadb89eDoris Liu        return true;
10070da918464276b110c43868caa272c97baadb89eDoris Liu    }
10170da918464276b110c43868caa272c97baadb89eDoris Liu
10270da918464276b110c43868caa272c97baadb89eDoris Liu    @Override
10370da918464276b110c43868caa272c97baadb89eDoris Liu    public boolean shouldAutoAdjustBottomBar() {
10470da918464276b110c43868caa272c97baadb89eDoris Liu        return true;
10570da918464276b110c43868caa272c97baadb89eDoris Liu    }
10670da918464276b110c43868caa272c97baadb89eDoris Liu
10711ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu    @Override
10811ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu    public void onPreviewFlipped() {
10911ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu        mController.updateCameraOrientation();
11011ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu    }
11111ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu
11236e56fba281292255a01ee00b4bee067fa09ab59Doris Liu    private class DecodeTask extends AsyncTask<Void, Void, Bitmap> {
11337f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling        private final byte [] mData;
114e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling        private final int mOrientation;
115e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling        private final boolean mMirror;
116c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu
11729da2db13029f8896018836693139a05d1139362Doris Liu        public DecodeTask(byte[] data, int orientation, boolean mirror) {
11837f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling            mData = data;
119ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu            mOrientation = orientation;
12029da2db13029f8896018836693139a05d1139362Doris Liu            mMirror = mirror;
121c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu        }
122c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu
123c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu        @Override
12436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu        protected Bitmap doInBackground(Void... params) {
12537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling            // Decode image in background.
126ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu            Bitmap bitmap = CameraUtil.downSample(mData, DOWN_SAMPLE_FACTOR);
12729da2db13029f8896018836693139a05d1139362Doris Liu            if (mOrientation != 0 || mMirror) {
128ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu                Matrix m = new Matrix();
12929da2db13029f8896018836693139a05d1139362Doris Liu                if (mMirror) {
13029da2db13029f8896018836693139a05d1139362Doris Liu                    // Flip horizontally
13129da2db13029f8896018836693139a05d1139362Doris Liu                    m.setScale(-1f, 1f);
13229da2db13029f8896018836693139a05d1139362Doris Liu                }
133cec75e408a2d451b90bac5f06e10906ffcafff33Andy Huibers                m.preRotate(mOrientation);
134ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu                return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m,
135ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu                        false);
136ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu            }
137ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu            return bitmap;
13837f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling        }
13937f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    }
140c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu
14136e56fba281292255a01ee00b4bee067fa09ab59Doris Liu    private class DecodeImageForReview extends DecodeTask {
14236e56fba281292255a01ee00b4bee067fa09ab59Doris Liu        public DecodeImageForReview(byte[] data, int orientation, boolean mirror) {
14336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu            super(data, orientation, mirror);
14436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu        }
14536e56fba281292255a01ee00b4bee067fa09ab59Doris Liu
14636e56fba281292255a01ee00b4bee067fa09ab59Doris Liu        @Override
14736e56fba281292255a01ee00b4bee067fa09ab59Doris Liu        protected void onPostExecute(Bitmap bitmap) {
14836e56fba281292255a01ee00b4bee067fa09ab59Doris Liu            if (isCancelled()) {
14936e56fba281292255a01ee00b4bee067fa09ab59Doris Liu                return;
15036e56fba281292255a01ee00b4bee067fa09ab59Doris Liu            }
15136e56fba281292255a01ee00b4bee067fa09ab59Doris Liu            mDecodeTaskForReview = null;
15236e56fba281292255a01ee00b4bee067fa09ab59Doris Liu        }
15336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu    }
15436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu
155d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    public PhotoUI(CameraActivity activity, PhotoController controller, View parent) {
156d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        mActivity = activity;
157d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        mController = controller;
158d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        mRootView = parent;
159d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
160f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu        ViewGroup moduleRoot = (ViewGroup) mRootView.findViewById(R.id.module_layout);
161d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        mActivity.getLayoutInflater().inflate(R.layout.photo_module,
162e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling                 moduleRoot, true);
163d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        initIndicators();
164482de029dc20e0a577388a602985fb31c3200309Doris Liu        mFocusUI = (FocusUI) mRootView.findViewById(R.id.focus_overlay);
165f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu        mPreviewOverlay = (PreviewOverlay) mRootView.findViewById(R.id.preview_overlay);
1666432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    }
1676432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu
168482de029dc20e0a577388a602985fb31c3200309Doris Liu    public FocusUI getFocusUI() {
169482de029dc20e0a577388a602985fb31c3200309Doris Liu        return mFocusUI;
170482de029dc20e0a577388a602985fb31c3200309Doris Liu    }
171482de029dc20e0a577388a602985fb31c3200309Doris Liu
172d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu    public void updatePreviewAspectRatio(float aspectRatio) {
173d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu        if (aspectRatio <= 0) {
174d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu            Log.e(TAG, "Invalid aspect ratio: " + aspectRatio);
175d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu            return;
176d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu        }
177d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu        if (aspectRatio < 1f) {
178d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu            aspectRatio = 1f / aspectRatio;
179d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu        }
180d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu
181d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu        if (mAspectRatio != aspectRatio) {
182d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu            mAspectRatio = aspectRatio;
183d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu            // Update transform matrix with the new aspect ratio.
18470da918464276b110c43868caa272c97baadb89eDoris Liu            mController.updatePreviewAspectRatio(mAspectRatio);
185d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu        }
186d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu    }
187d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu
188dcccc510652b835fdbd39310a07849af8203052aAngus Kong    @Override
1896432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
190d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren        mController.onPreviewUIReady();
1916432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    }
192d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
193dcccc510652b835fdbd39310a07849af8203052aAngus Kong    @Override
1946432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
1956432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        // Ignored, Camera does all the work for us
1966432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    }
1976432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu
198dcccc510652b835fdbd39310a07849af8203052aAngus Kong    @Override
1996432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
200d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren        mController.onPreviewUIDestroyed();
201d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren        return true;
2026432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    }
2036432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu
2047b265a6b2f55c6ae7afc30e63ba324c4084a5d8eztenghui    @Override
2056432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
206d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
207d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
208d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    public View getRootView() {
209d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        return mRootView;
210d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
211d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
212d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    private void initIndicators() {
2130744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        // TODO init toggle buttons on bottom bar here
214d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
215d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
216b1641f5df0cf839b54385ea4d2e43521620fc237Erin Dahlgren    public void onCameraOpened(Camera.Parameters params) {
217eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague        initializeZoom(params);
218eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague    }
219eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague
2200a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren    public void animateCapture(final byte[] jpegData, int orientation, boolean mirror) {
2210a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren        // Decode jpeg byte array and then animate the jpeg
2220a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren        DecodeTask task = new DecodeTask(jpegData, orientation, mirror);
2230a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren        task.execute();
224eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague    }
225d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
226d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    // called from onResume but only the first time
227ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan    public void initializeFirstTime() {
2280744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
229d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
230d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
231d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    // called from onResume every other time
232d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    public void initializeSecondTime(Camera.Parameters params) {
233d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        initializeZoom(params);
234d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        if (mController.isImageCaptureIntent()) {
235d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb            hidePostCaptureAlert();
236d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        }
237357b7673f03d9b45d281d585cc3f4f87dc7d727bErin Dahlgren        // Removes pie menu.
238d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
239d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
2406a83d528b09c55ade6ad44b82c81d4476ac57441Doris Liu    public void showLocationDialog() {
241491c628441a58f2dd4b5a5745147552d3f3d9decErin Dahlgren        AlertDialog alert = mActivity.getFirstTimeLocationAlert();
242491c628441a58f2dd4b5a5745147552d3f3d9decErin Dahlgren        alert.show();
2436a83d528b09c55ade6ad44b82c81d4476ac57441Doris Liu    }
2446a83d528b09c55ade6ad44b82c81d4476ac57441Doris Liu
245d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    public void initializeZoom(Camera.Parameters params) {
246f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu        if ((params == null) || !params.isZoomSupported()) return;
247d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        mZoomMax = params.getMaxZoom();
248d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        mZoomRatios = params.getZoomRatios();
249d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        // Currently we use immediate zoom for fast zooming to get better UX and
250d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        // there is no plan to take advantage of the smooth zoom.
251f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu        // TODO: Need to setup a path to AppUI to do this
252f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu        mPreviewOverlay.setupZoom(mZoomMax, params.getZoom(), mZoomRatios, new ZoomChangeListener());
253d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
254d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
255c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu    public void animateFlash() {
2561dfe7828fd60741b9752553af3ee439c04e758a0Doris Liu        mController.startPreCaptureAnimation();
257c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu    }
258c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu
259d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    public boolean onBackPressed() {
260d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        // In image capture mode, back button should:
261d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        // 1) if there is any popup, dismiss them, 2) otherwise, get out of
262d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        // image capture
263d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        if (mController.isImageCaptureIntent()) {
264c3679c0961521165499380c77344acc69072b2acDoris Liu            mController.onCaptureCancelled();
265d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb            return true;
266d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        } else if (!mController.isCameraIdle()) {
267d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb            // ignore backs while we're taking a picture
268d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb            return true;
269d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        } else {
270c3679c0961521165499380c77344acc69072b2acDoris Liu            return false;
271d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        }
272d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
273d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
27436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu    protected void showCapturedImageForReview(byte[] jpegData, int orientation, boolean mirror) {
27536e56fba281292255a01ee00b4bee067fa09ab59Doris Liu        mDecodeTaskForReview = new DecodeImageForReview(jpegData, orientation, mirror);
27636e56fba281292255a01ee00b4bee067fa09ab59Doris Liu        mDecodeTaskForReview.execute();
2774efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
2784efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        mActivity.getCameraAppUI().transitionToIntentReviewLayout();
279d31cdfeb1035df8ba939e877031769f0df247aa6Doris Liu        pauseFaceDetection();
280d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
281d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
282d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    protected void hidePostCaptureAlert() {
28336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu        if (mDecodeTaskForReview != null) {
28436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu            mDecodeTaskForReview.cancel(true);
28536e56fba281292255a01ee00b4bee067fa09ab59Doris Liu        }
286d31cdfeb1035df8ba939e877031769f0df247aa6Doris Liu        resumeFaceDetection();
287d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
288d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
289d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    public void setDisplayOrientation(int orientation) {
290d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        if (mFaceView != null) {
291d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb            mFaceView.setDisplayOrientation(orientation);
292d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        }
293d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
294d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
295d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    // shutter button handling
296d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
297d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    public boolean isShutterPressed() {
2980744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        return false;
299d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
300d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
3018890194726507573fd230fba7d4042ed00b363e4Sascha Haeberling    /**
3028890194726507573fd230fba7d4042ed00b363e4Sascha Haeberling     * Enables or disables the shutter button.
3038890194726507573fd230fba7d4042ed00b363e4Sascha Haeberling     */
3046432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public void enableShutter(boolean enabled) {
3050744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
3066432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    }
307d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
3086432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public void pressShutterButton() {
3090744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
3106432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    }
311d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
312f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu    private class ZoomChangeListener implements PreviewOverlay.OnZoomChangedListener {
313d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        @Override
314d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        public void onZoomValueChanged(int index) {
315f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu            mController.onZoomChanged(index);
316d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        }
317d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
318d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        @Override
319d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        public void onZoomStart() {
320d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        }
321d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
322d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        @Override
323d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        public void onZoomEnd() {
324d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        }
325d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
326d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
3276432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public void setSwipingEnabled(boolean enable) {
3286432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        mActivity.setSwipingEnabled(enable);
329d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
330d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
331d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    public void onPause() {
332d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        if (mFaceView != null) mFaceView.clear();
333d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
334d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
335d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    public void clearFaces() {
3360744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        if (mFaceView != null) {
3370744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen            mFaceView.clear();
3380744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        }
339d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
340d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
341d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    public void pauseFaceDetection() {
342d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        if (mFaceView != null) mFaceView.pause();
343d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
344d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
345d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    public void resumeFaceDetection() {
346d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        if (mFaceView != null) mFaceView.resume();
347d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
348d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
349d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    public void onStartFaceDetection(int orientation, boolean mirror) {
350d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu        if (mFaceView != null) {
351d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu            mFaceView.clear();
352d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu            mFaceView.setVisibility(View.VISIBLE);
353d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu            mFaceView.setDisplayOrientation(orientation);
354d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu            mFaceView.setMirror(mirror);
355d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu            mFaceView.resume();
356d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu        }
357d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
358d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
359d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    @Override
3609e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong    public void onFaceDetection(Face[] faces, CameraManager.CameraProxy camera) {
361d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu        if (mFaceView != null) {
362d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu            mFaceView.setFaces(faces);
363d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu        }
364d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb    }
365d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb
36659401045bf479b2617c981075aec92190ec59aebDoris Liu    /**
3672bacca795a1b0adb0daf515c43c48234b44bbba5Angus Kong     * Returns a {@link com.android.camera.ui.PreviewStatusListener.PreviewAreaChangedListener}
36859401045bf479b2617c981075aec92190ec59aebDoris Liu     * that should be registered to listen to preview area change.
36959401045bf479b2617c981075aec92190ec59aebDoris Liu     */
3702bacca795a1b0adb0daf515c43c48234b44bbba5Angus Kong    public PreviewAreaChangedListener getPreviewAreaSizeChangedListener() {
37159401045bf479b2617c981075aec92190ec59aebDoris Liu        return mFaceView;
37259401045bf479b2617c981075aec92190ec59aebDoris Liu    }
37359401045bf479b2617c981075aec92190ec59aebDoris Liu
374d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb}
375