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 19db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liuimport android.app.Dialog; 20db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liuimport android.content.DialogInterface; 2137f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberlingimport android.graphics.Bitmap; 226432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liuimport android.graphics.Matrix; 236c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liuimport android.graphics.RectF; 246432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liuimport android.graphics.SurfaceTexture; 25d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.hardware.Camera.Face; 2637f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberlingimport android.os.AsyncTask; 271d943647c5b632588c4858ded04770e846341f1bSascha Haeberlingimport android.os.Build; 28f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liuimport android.view.GestureDetector; 29f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liuimport android.view.MotionEvent; 30d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.view.View; 31d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.view.ViewGroup; 32b4a2222950f627a39267636fba19649974cb8734Spike Spragueimport android.widget.FrameLayout; 33b4a2222950f627a39267636fba19649974cb8734Spike Spragueimport android.widget.ImageView; 34d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 35d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport com.android.camera.FocusOverlayManager.FocusUI; 3662b4c3c0da3abd397b3790820359927784c50bc2Andy Huibersimport com.android.camera.debug.DebugPropertyHelper; 375596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log; 386c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liuimport com.android.camera.ui.CountDownView; 39d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport com.android.camera.ui.FaceView; 40f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liuimport com.android.camera.ui.PreviewOverlay; 4106db742814dd635d100639f977fcfdc904deb778Doris Liuimport com.android.camera.ui.PreviewStatusListener; 422631a15a37b890f4ee720c5a4bbe3e654524deb6Alan Newbergerimport com.android.camera.util.ApiHelper; 43b50b5cbfbc0a67db6fc43373363b10381c9c61a3Angus Kongimport com.android.camera.util.CameraUtil; 442631a15a37b890f4ee720c5a4bbe3e654524deb6Alan Newbergerimport com.android.camera.util.GservicesHelper; 45db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liuimport com.android.camera.widget.AspectRatioDialogLayout; 46db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liuimport com.android.camera.widget.AspectRatioSelector; 47db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liuimport com.android.camera.widget.LocationDialogLayout; 488e963a5a6016d246184ed65906f9d103e92b17e2Sascha Haeberlingimport com.android.camera2.R; 495a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraAgent; 504c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberlingimport com.android.ex.camera2.portability.CameraCapabilities; 515a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraSettings; 52b50b5cbfbc0a67db6fc43373363b10381c9c61a3Angus Kong 53482de029dc20e0a577388a602985fb31c3200309Doris Liupublic class PhotoUI implements PreviewStatusListener, 545a344964cb003525727c31d295ca3a592c245606Sol Boucher CameraAgent.CameraFaceDetectionCallback, PreviewStatusListener.PreviewAreaChangedListener { 55d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 565596b4c902dcb685928b43678f428746ca5ffd08Angus Kong private static final Log.Tag TAG = new Log.Tag("PhotoUI"); 5737f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling private static final int DOWN_SAMPLE_FACTOR = 4; 5870da918464276b110c43868caa272c97baadb89eDoris Liu private static final float UNSET = 0f; 590f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague 60f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu private final PreviewOverlay mPreviewOverlay; 61482de029dc20e0a577388a602985fb31c3200309Doris Liu private final FocusUI mFocusUI; 62e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling private final CameraActivity mActivity; 63e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling private final PhotoController mController; 64d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 65e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling private final View mRootView; 66db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu private Dialog mDialog = null; 67d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 68d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu // TODO: Remove face view logic if UX does not bring it back within a month. 6962b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers private final FaceView mFaceView; 7036e56fba281292255a01ee00b4bee067fa09ab59Doris Liu private DecodeImageForReview mDecodeTaskForReview = null; 71d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 722192fbaaf598d4440a8d537a70095ea56bc9a5ebSol Boucher private float mZoomMax; 73d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 74d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb private int mPreviewWidth = 0; 75d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb private int mPreviewHeight = 0; 7670da918464276b110c43868caa272c97baadb89eDoris Liu private float mAspectRatio = UNSET; 770744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 78b4a2222950f627a39267636fba19649974cb8734Spike Sprague private ImageView mIntentReviewImageView; 79b4a2222950f627a39267636fba19649974cb8734Spike Sprague 8006db742814dd635d100639f977fcfdc904deb778Doris Liu private final GestureDetector.OnGestureListener mPreviewGestureListener 8106db742814dd635d100639f977fcfdc904deb778Doris Liu = new GestureDetector.SimpleOnGestureListener() { 8206db742814dd635d100639f977fcfdc904deb778Doris Liu @Override 8306db742814dd635d100639f977fcfdc904deb778Doris Liu public boolean onSingleTapUp(MotionEvent ev) { 8406db742814dd635d100639f977fcfdc904deb778Doris Liu mController.onSingleTapUp(null, (int) ev.getX(), (int) ev.getY()); 8506db742814dd635d100639f977fcfdc904deb778Doris Liu return true; 8606db742814dd635d100639f977fcfdc904deb778Doris Liu } 8706db742814dd635d100639f977fcfdc904deb778Doris Liu }; 88db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu private final DialogInterface.OnDismissListener mOnDismissListener 89db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu = new DialogInterface.OnDismissListener() { 90db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu @Override 91db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu public void onDismiss(DialogInterface dialog) { 92db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog = null; 93db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 94db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu }; 9508b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu private Runnable mRunnableForNextFrame = null; 964c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberling private final CountDownView mCountdownView; 970744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 9806db742814dd635d100639f977fcfdc904deb778Doris Liu @Override 9906db742814dd635d100639f977fcfdc904deb778Doris Liu public GestureDetector.OnGestureListener getGestureListener() { 10006db742814dd635d100639f977fcfdc904deb778Doris Liu return mPreviewGestureListener; 10106db742814dd635d100639f977fcfdc904deb778Doris Liu } 10206db742814dd635d100639f977fcfdc904deb778Doris Liu 1034a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu @Override 104d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren public View.OnTouchListener getTouchListener() { 105d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren return null; 106d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren } 107d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren 108d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren @Override 1094a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu public void onPreviewLayoutChanged(View v, int left, int top, int right, 1104a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 1114a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu int width = right - left; 1124a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu int height = bottom - top; 1134a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu if (mPreviewWidth != width || mPreviewHeight != height) { 1144a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu mPreviewWidth = width; 1154a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu mPreviewHeight = height; 116d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 1174a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu } 118d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 11970da918464276b110c43868caa272c97baadb89eDoris Liu @Override 12070da918464276b110c43868caa272c97baadb89eDoris Liu public boolean shouldAutoAdjustTransformMatrixOnLayout() { 12170da918464276b110c43868caa272c97baadb89eDoris Liu return true; 12270da918464276b110c43868caa272c97baadb89eDoris Liu } 12370da918464276b110c43868caa272c97baadb89eDoris Liu 12470da918464276b110c43868caa272c97baadb89eDoris Liu @Override 12570da918464276b110c43868caa272c97baadb89eDoris Liu public boolean shouldAutoAdjustBottomBar() { 12670da918464276b110c43868caa272c97baadb89eDoris Liu return true; 12770da918464276b110c43868caa272c97baadb89eDoris Liu } 12870da918464276b110c43868caa272c97baadb89eDoris Liu 12911ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu @Override 13011ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu public void onPreviewFlipped() { 13111ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu mController.updateCameraOrientation(); 13211ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu } 13311ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu 13408b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu /** 13508b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu * Sets the runnable to run when the next frame comes in. 13608b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu */ 13708b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu public void setRunnableForNextFrame(Runnable runnable) { 13808b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu mRunnableForNextFrame = runnable; 13908b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu } 14008b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu 1416c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu /** 1426c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu * Starts the countdown timer. 1436c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu * 1446c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu * @param sec seconds to countdown 1456c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu */ 1466c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu public void startCountdown(int sec) { 1476c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu mCountdownView.startCountDown(sec); 1486c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu } 1496c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu 1506c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu /** 1516c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu * Sets a listener that gets notified when the countdown is finished. 1526c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu */ 1536c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu public void setCountdownFinishedListener(CountDownView.OnCountDownStatusListener listener) { 1546c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu mCountdownView.setCountDownStatusListener(listener); 1556c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu } 1566c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu 1576c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu /** 1586c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu * Returns whether the countdown is on-going. 1596c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu */ 1606c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu public boolean isCountingDown() { 1616c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu return mCountdownView.isCountingDown(); 1626c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu } 1636c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu 1646c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu /** 1656c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu * Cancels the on-going countdown, if any. 1666c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu */ 1676c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu public void cancelCountDown() { 1686c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu mCountdownView.cancelCountDown(); 1696c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu } 1706c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu 1716c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu @Override 1726c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu public void onPreviewAreaChanged(RectF previewArea) { 1736c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu if (mFaceView != null) { 1746c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu mFaceView.onPreviewAreaChanged(previewArea); 1756c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu } 1766c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu mCountdownView.onPreviewAreaChanged(previewArea); 1776c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu } 1786c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu 17936e56fba281292255a01ee00b4bee067fa09ab59Doris Liu private class DecodeTask extends AsyncTask<Void, Void, Bitmap> { 18037f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling private final byte [] mData; 181e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling private final int mOrientation; 182e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling private final boolean mMirror; 183c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu 18429da2db13029f8896018836693139a05d1139362Doris Liu public DecodeTask(byte[] data, int orientation, boolean mirror) { 18537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling mData = data; 186ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu mOrientation = orientation; 18729da2db13029f8896018836693139a05d1139362Doris Liu mMirror = mirror; 188c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu } 189c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu 190c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu @Override 19136e56fba281292255a01ee00b4bee067fa09ab59Doris Liu protected Bitmap doInBackground(Void... params) { 19237f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling // Decode image in background. 193ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu Bitmap bitmap = CameraUtil.downSample(mData, DOWN_SAMPLE_FACTOR); 19429da2db13029f8896018836693139a05d1139362Doris Liu if (mOrientation != 0 || mMirror) { 195ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu Matrix m = new Matrix(); 19629da2db13029f8896018836693139a05d1139362Doris Liu if (mMirror) { 19729da2db13029f8896018836693139a05d1139362Doris Liu // Flip horizontally 19829da2db13029f8896018836693139a05d1139362Doris Liu m.setScale(-1f, 1f); 19929da2db13029f8896018836693139a05d1139362Doris Liu } 200cec75e408a2d451b90bac5f06e10906ffcafff33Andy Huibers m.preRotate(mOrientation); 201ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, 202ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu false); 203ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu } 204ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu return bitmap; 20537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling } 20637f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling } 207c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu 20836e56fba281292255a01ee00b4bee067fa09ab59Doris Liu private class DecodeImageForReview extends DecodeTask { 20936e56fba281292255a01ee00b4bee067fa09ab59Doris Liu public DecodeImageForReview(byte[] data, int orientation, boolean mirror) { 21036e56fba281292255a01ee00b4bee067fa09ab59Doris Liu super(data, orientation, mirror); 21136e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 21236e56fba281292255a01ee00b4bee067fa09ab59Doris Liu 21336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu @Override 21436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu protected void onPostExecute(Bitmap bitmap) { 21536e56fba281292255a01ee00b4bee067fa09ab59Doris Liu if (isCancelled()) { 21636e56fba281292255a01ee00b4bee067fa09ab59Doris Liu return; 21736e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 218b4a2222950f627a39267636fba19649974cb8734Spike Sprague 219b4a2222950f627a39267636fba19649974cb8734Spike Sprague mIntentReviewImageView.setImageBitmap(bitmap); 220b4a2222950f627a39267636fba19649974cb8734Spike Sprague showIntentReviewImageView(); 221b4a2222950f627a39267636fba19649974cb8734Spike Sprague 22236e56fba281292255a01ee00b4bee067fa09ab59Doris Liu mDecodeTaskForReview = null; 22336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 22436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 22536e56fba281292255a01ee00b4bee067fa09ab59Doris Liu 226d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public PhotoUI(CameraActivity activity, PhotoController controller, View parent) { 227d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mActivity = activity; 228d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mController = controller; 229d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mRootView = parent; 230d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 231f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu ViewGroup moduleRoot = (ViewGroup) mRootView.findViewById(R.id.module_layout); 232d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mActivity.getLayoutInflater().inflate(R.layout.photo_module, 233e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling moduleRoot, true); 234d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb initIndicators(); 235482de029dc20e0a577388a602985fb31c3200309Doris Liu mFocusUI = (FocusUI) mRootView.findViewById(R.id.focus_overlay); 236f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu mPreviewOverlay = (PreviewOverlay) mRootView.findViewById(R.id.preview_overlay); 2376c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu mCountdownView = (CountDownView) mRootView.findViewById(R.id.count_down_view); 23862b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers // Show faces if we are in debug mode. 23962b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers if (DebugPropertyHelper.showCaptureDebugUI()) { 24062b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers mFaceView = (FaceView) mRootView.findViewById(R.id.face_view); 24162b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers } else { 24262b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers mFaceView = null; 24362b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers } 244b4a2222950f627a39267636fba19649974cb8734Spike Sprague 245b4a2222950f627a39267636fba19649974cb8734Spike Sprague if (mController.isImageCaptureIntent()) { 24602b9b9af097ac7886ec1d23392cd87c9fbcb186fSpike Sprague initIntentReviewImageView(); 247b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 248b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 249b4a2222950f627a39267636fba19649974cb8734Spike Sprague 25002b9b9af097ac7886ec1d23392cd87c9fbcb186fSpike Sprague private void initIntentReviewImageView() { 25102b9b9af097ac7886ec1d23392cd87c9fbcb186fSpike Sprague mIntentReviewImageView = (ImageView) mRootView.findViewById(R.id.intent_review_imageview); 252b4a2222950f627a39267636fba19649974cb8734Spike Sprague mActivity.getCameraAppUI().addPreviewAreaChangedListener( 253b4a2222950f627a39267636fba19649974cb8734Spike Sprague new PreviewStatusListener.PreviewAreaChangedListener() { 254b4a2222950f627a39267636fba19649974cb8734Spike Sprague @Override 255b4a2222950f627a39267636fba19649974cb8734Spike Sprague public void onPreviewAreaChanged(RectF previewArea) { 256b4a2222950f627a39267636fba19649974cb8734Spike Sprague FrameLayout.LayoutParams params = 257b4a2222950f627a39267636fba19649974cb8734Spike Sprague (FrameLayout.LayoutParams) mIntentReviewImageView.getLayoutParams(); 258b4a2222950f627a39267636fba19649974cb8734Spike Sprague params.width = (int) previewArea.width(); 259b4a2222950f627a39267636fba19649974cb8734Spike Sprague params.height = (int) previewArea.height(); 260b4a2222950f627a39267636fba19649974cb8734Spike Sprague params.setMargins((int) previewArea.left, (int) previewArea.top, 0, 0); 261b4a2222950f627a39267636fba19649974cb8734Spike Sprague mIntentReviewImageView.setLayoutParams(params); 262b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 263b4a2222950f627a39267636fba19649974cb8734Spike Sprague }); 264b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 265b4a2222950f627a39267636fba19649974cb8734Spike Sprague 266b4a2222950f627a39267636fba19649974cb8734Spike Sprague /** 267b4a2222950f627a39267636fba19649974cb8734Spike Sprague * Show the image review over the live preview for intent captures. 268b4a2222950f627a39267636fba19649974cb8734Spike Sprague */ 269b4a2222950f627a39267636fba19649974cb8734Spike Sprague public void showIntentReviewImageView() { 270b4a2222950f627a39267636fba19649974cb8734Spike Sprague if (mIntentReviewImageView != null) { 271b4a2222950f627a39267636fba19649974cb8734Spike Sprague mIntentReviewImageView.setVisibility(View.VISIBLE); 272b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 2736432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu } 2746432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu 275b4a2222950f627a39267636fba19649974cb8734Spike Sprague /** 276b4a2222950f627a39267636fba19649974cb8734Spike Sprague * Hide the image review over the live preview for intent captures. 277b4a2222950f627a39267636fba19649974cb8734Spike Sprague */ 278b4a2222950f627a39267636fba19649974cb8734Spike Sprague public void hideIntentReviewImageView() { 279b4a2222950f627a39267636fba19649974cb8734Spike Sprague if (mIntentReviewImageView != null) { 280b4a2222950f627a39267636fba19649974cb8734Spike Sprague mIntentReviewImageView.setVisibility(View.INVISIBLE); 281b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 282b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 283b4a2222950f627a39267636fba19649974cb8734Spike Sprague 284b4a2222950f627a39267636fba19649974cb8734Spike Sprague 285482de029dc20e0a577388a602985fb31c3200309Doris Liu public FocusUI getFocusUI() { 286482de029dc20e0a577388a602985fb31c3200309Doris Liu return mFocusUI; 287482de029dc20e0a577388a602985fb31c3200309Doris Liu } 288482de029dc20e0a577388a602985fb31c3200309Doris Liu 289d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu public void updatePreviewAspectRatio(float aspectRatio) { 290d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu if (aspectRatio <= 0) { 291d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu Log.e(TAG, "Invalid aspect ratio: " + aspectRatio); 292d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu return; 293d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu } 294d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu if (aspectRatio < 1f) { 295d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu aspectRatio = 1f / aspectRatio; 296d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu } 297d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu 298d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu if (mAspectRatio != aspectRatio) { 299d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu mAspectRatio = aspectRatio; 300d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu // Update transform matrix with the new aspect ratio. 30170da918464276b110c43868caa272c97baadb89eDoris Liu mController.updatePreviewAspectRatio(mAspectRatio); 302d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu } 303d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu } 304d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu 305dcccc510652b835fdbd39310a07849af8203052aAngus Kong @Override 3066432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 307d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren mController.onPreviewUIReady(); 3086432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu } 309d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 310dcccc510652b835fdbd39310a07849af8203052aAngus Kong @Override 3116432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 3126432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu // Ignored, Camera does all the work for us 3136432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu } 3146432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu 315dcccc510652b835fdbd39310a07849af8203052aAngus Kong @Override 3166432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 317d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren mController.onPreviewUIDestroyed(); 318d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren return true; 3196432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu } 3206432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu 3217b265a6b2f55c6ae7afc30e63ba324c4084a5d8eztenghui @Override 3226432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public void onSurfaceTextureUpdated(SurfaceTexture surface) { 32308b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu if (mRunnableForNextFrame != null) { 32408b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu mRootView.post(mRunnableForNextFrame); 32508b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu mRunnableForNextFrame = null; 32608b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu } 327d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 328d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 329d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public View getRootView() { 330d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb return mRootView; 331d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 332d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 333d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb private void initIndicators() { 3340744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen // TODO init toggle buttons on bottom bar here 335d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 336d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 3376607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong public void onCameraOpened(CameraCapabilities capabilities, CameraSettings settings) { 3386607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong initializeZoom(capabilities, settings); 339eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague } 340eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague 3410a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren public void animateCapture(final byte[] jpegData, int orientation, boolean mirror) { 3420a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren // Decode jpeg byte array and then animate the jpeg 3430a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren DecodeTask task = new DecodeTask(jpegData, orientation, mirror); 3440a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren task.execute(); 345eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague } 346d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 347d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // called from onResume but only the first time 348ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan public void initializeFirstTime() { 3490744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 350d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 351d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 352d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // called from onResume every other time 3536607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong public void initializeSecondTime(CameraCapabilities capabilities, CameraSettings settings) { 3546607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong initializeZoom(capabilities, settings); 355d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mController.isImageCaptureIntent()) { 356d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb hidePostCaptureAlert(); 357d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 358d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 359d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 360db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu public void showLocationAndAspectRatioDialog( 361db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu final PhotoModule.LocationDialogCallback locationCallback, 362db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu final PhotoModule.AspectRatioDialogCallback aspectRatioDialogCallback) { 363db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu setDialog(new Dialog(mActivity, 364db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu android.R.style.Theme_Black_NoTitleBar_Fullscreen)); 365db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu final LocationDialogLayout locationDialogLayout = (LocationDialogLayout) mActivity 366db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu .getLayoutInflater().inflate(R.layout.location_dialog_layout, null); 367db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu locationDialogLayout.setLocationTaggingSelectionListener( 368db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu new LocationDialogLayout.LocationTaggingSelectionListener() { 369db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu @Override 370db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu public void onLocationTaggingSelected(boolean selected) { 371db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu // Update setting. 372db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu locationCallback.onLocationTaggingSelected(selected); 3731d943647c5b632588c4858ded04770e846341f1bSascha Haeberling 3741d943647c5b632588c4858ded04770e846341f1bSascha Haeberling if (showAspectRatioDialogOnThisDevice()) { 3751d943647c5b632588c4858ded04770e846341f1bSascha Haeberling // Go to next page. 3761d943647c5b632588c4858ded04770e846341f1bSascha Haeberling showAspectRatioDialog(aspectRatioDialogCallback, mDialog); 3771d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } else { 3781d943647c5b632588c4858ded04770e846341f1bSascha Haeberling // If we don't want to show the aspect ratio dialog, 3791d943647c5b632588c4858ded04770e846341f1bSascha Haeberling // dismiss the dialog right after the user chose the 3801d943647c5b632588c4858ded04770e846341f1bSascha Haeberling // location setting. 3811d943647c5b632588c4858ded04770e846341f1bSascha Haeberling if (mDialog != null) { 3821d943647c5b632588c4858ded04770e846341f1bSascha Haeberling mDialog.dismiss(); 3831d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } 3841d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } 385db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 386db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu }); 387db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.setContentView(locationDialogLayout, new ViewGroup.LayoutParams( 388db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 389db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.show(); 390db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 391db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu 392db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu /** 393db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu * Dismisses previous dialog if any, sets current dialog to the given dialog, 394db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu * and set the on dismiss listener for the given dialog. 395db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu * @param dialog dialog to show 396db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu */ 397db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu private void setDialog(Dialog dialog) { 398db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu if (mDialog != null) { 399db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.setOnDismissListener(null); 400db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.dismiss(); 401db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 402db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog = dialog; 403db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu if (mDialog != null) { 404db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.setOnDismissListener(mOnDismissListener); 405db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 406db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 407db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu 4084c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberling /** 4094c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberling * @return Whether the dialog was shown. 4104c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberling */ 4114c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberling public boolean showAspectRatioDialog(final PhotoModule.AspectRatioDialogCallback callback) { 4121d943647c5b632588c4858ded04770e846341f1bSascha Haeberling if (showAspectRatioDialogOnThisDevice()) { 4131d943647c5b632588c4858ded04770e846341f1bSascha Haeberling setDialog(new Dialog(mActivity, android.R.style.Theme_Black_NoTitleBar_Fullscreen)); 4141d943647c5b632588c4858ded04770e846341f1bSascha Haeberling showAspectRatioDialog(callback, mDialog); 4154c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberling return true; 4164c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberling } else { 4174c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberling return false; 4181d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } 419db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 420db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu 4214c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberling private boolean showAspectRatioDialog(final PhotoModule.AspectRatioDialogCallback callback, 422db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu final Dialog aspectRatioDialog) { 423db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu if (aspectRatioDialog == null) { 424db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu Log.e(TAG, "Dialog for aspect ratio is null."); 4254c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberling return false; 426db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 427db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu final AspectRatioDialogLayout aspectRatioDialogLayout = 428db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu (AspectRatioDialogLayout) mActivity 429db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu .getLayoutInflater().inflate(R.layout.aspect_ratio_dialog_layout, null); 430db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu aspectRatioDialogLayout.initialize( 431db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu new AspectRatioDialogLayout.AspectRatioChangedListener() { 432db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu @Override 433db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu public void onAspectRatioChanged(AspectRatioSelector.AspectRatio aspectRatio) { 434db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu // callback to set picture size. 43508b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu callback.onAspectRatioSelected(aspectRatio, new Runnable() { 43608b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu @Override 43708b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu public void run() { 43808b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu if (mDialog != null) { 43908b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu mDialog.dismiss(); 44008b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu } 44108b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu } 44208b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu }); 443db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 444e811b29f6707a6ea8f066e6f5b9cb0fc99d2dcd6Sascha Haeberling }, callback.getCurrentAspectRatio()); 445db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu aspectRatioDialog.setContentView(aspectRatioDialogLayout, new ViewGroup.LayoutParams( 446db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 447db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu aspectRatioDialog.show(); 4484c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberling return true; 4496a83d528b09c55ade6ad44b82c81d4476ac57441Doris Liu } 4506a83d528b09c55ade6ad44b82c81d4476ac57441Doris Liu 4511d943647c5b632588c4858ded04770e846341f1bSascha Haeberling /** 4521d943647c5b632588c4858ded04770e846341f1bSascha Haeberling * @return Whether this is a device that we should show the aspect ratio 4531d943647c5b632588c4858ded04770e846341f1bSascha Haeberling * intro dialog on. 4541d943647c5b632588c4858ded04770e846341f1bSascha Haeberling */ 4551d943647c5b632588c4858ded04770e846341f1bSascha Haeberling private boolean showAspectRatioDialogOnThisDevice() { 4562631a15a37b890f4ee720c5a4bbe3e654524deb6Alan Newberger // We only want to show that dialog on N4/N5/N6 4572631a15a37b890f4ee720c5a4bbe3e654524deb6Alan Newberger // Don't show if using API2 portability, b/17462976 4582631a15a37b890f4ee720c5a4bbe3e654524deb6Alan Newberger return !GservicesHelper.useCamera2ApiThroughPortabilityLayer(mActivity) && 4592631a15a37b890f4ee720c5a4bbe3e654524deb6Alan Newberger (ApiHelper.IS_NEXUS_4 || ApiHelper.IS_NEXUS_5 || ApiHelper.IS_NEXUS_6); 4601d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } 4611d943647c5b632588c4858ded04770e846341f1bSascha Haeberling 4626607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong public void initializeZoom(CameraCapabilities capabilities, CameraSettings settings) { 4636607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong if ((capabilities == null) || settings == null || 4646607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong !capabilities.supports(CameraCapabilities.Feature.ZOOM)) { 4651d943647c5b632588c4858ded04770e846341f1bSascha Haeberling return; 4661d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } 4672192fbaaf598d4440a8d537a70095ea56bc9a5ebSol Boucher mZoomMax = capabilities.getMaxZoomRatio(); 468d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // Currently we use immediate zoom for fast zooming to get better UX and 469d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // there is no plan to take advantage of the smooth zoom. 470f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu // TODO: Need to setup a path to AppUI to do this 4712192fbaaf598d4440a8d537a70095ea56bc9a5ebSol Boucher mPreviewOverlay.setupZoom(mZoomMax, settings.getCurrentZoomRatio(), 4726607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong new ZoomChangeListener()); 473d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 474d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 475c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu public void animateFlash() { 4761dfe7828fd60741b9752553af3ee439c04e758a0Doris Liu mController.startPreCaptureAnimation(); 477c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu } 478c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu 479d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public boolean onBackPressed() { 480d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // In image capture mode, back button should: 481d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // 1) if there is any popup, dismiss them, 2) otherwise, get out of 482d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // image capture 483d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mController.isImageCaptureIntent()) { 484c3679c0961521165499380c77344acc69072b2acDoris Liu mController.onCaptureCancelled(); 485d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb return true; 486d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } else if (!mController.isCameraIdle()) { 487d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // ignore backs while we're taking a picture 488d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb return true; 489d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } else { 490c3679c0961521165499380c77344acc69072b2acDoris Liu return false; 491d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 492d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 493d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 49436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu protected void showCapturedImageForReview(byte[] jpegData, int orientation, boolean mirror) { 49536e56fba281292255a01ee00b4bee067fa09ab59Doris Liu mDecodeTaskForReview = new DecodeImageForReview(jpegData, orientation, mirror); 49636e56fba281292255a01ee00b4bee067fa09ab59Doris Liu mDecodeTaskForReview.execute(); 4974efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 4984efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mActivity.getCameraAppUI().transitionToIntentReviewLayout(); 499d31cdfeb1035df8ba939e877031769f0df247aa6Doris Liu pauseFaceDetection(); 500d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 501d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 502d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb protected void hidePostCaptureAlert() { 50336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu if (mDecodeTaskForReview != null) { 50436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu mDecodeTaskForReview.cancel(true); 50536e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 506d31cdfeb1035df8ba939e877031769f0df247aa6Doris Liu resumeFaceDetection(); 507d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 508d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 509d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void setDisplayOrientation(int orientation) { 510d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mFaceView != null) { 511d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mFaceView.setDisplayOrientation(orientation); 512d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 513d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 514d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 515f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu private class ZoomChangeListener implements PreviewOverlay.OnZoomChangedListener { 516d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb @Override 5172192fbaaf598d4440a8d537a70095ea56bc9a5ebSol Boucher public void onZoomValueChanged(float ratio) { 5182192fbaaf598d4440a8d537a70095ea56bc9a5ebSol Boucher mController.onZoomChanged(ratio); 519d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 520d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 521d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb @Override 522d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onZoomStart() { 523d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 524d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 525d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb @Override 526d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onZoomEnd() { 527d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 528d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 529d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 5306432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public void setSwipingEnabled(boolean enable) { 5316432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu mActivity.setSwipingEnabled(enable); 532d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 533d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 534d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onPause() { 5351d943647c5b632588c4858ded04770e846341f1bSascha Haeberling if (mFaceView != null) { 5361d943647c5b632588c4858ded04770e846341f1bSascha Haeberling mFaceView.clear(); 5371d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } 538db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu if (mDialog != null) { 539db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.dismiss(); 540db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 5417351415ddfaf7f563a4a12c9204e6feb20fdf49dAlan Newberger // recalculate aspect ratio when restarting. 5427351415ddfaf7f563a4a12c9204e6feb20fdf49dAlan Newberger mAspectRatio = 0.0f; 543d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 544d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 545d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void clearFaces() { 5460744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen if (mFaceView != null) { 5470744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen mFaceView.clear(); 5480744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 549d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 550d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 551d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void pauseFaceDetection() { 5521d943647c5b632588c4858ded04770e846341f1bSascha Haeberling if (mFaceView != null) { 5531d943647c5b632588c4858ded04770e846341f1bSascha Haeberling mFaceView.pause(); 5541d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } 555d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 556d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 557d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void resumeFaceDetection() { 5581d943647c5b632588c4858ded04770e846341f1bSascha Haeberling if (mFaceView != null) { 5591d943647c5b632588c4858ded04770e846341f1bSascha Haeberling mFaceView.resume(); 5601d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } 561d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 562d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 563d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onStartFaceDetection(int orientation, boolean mirror) { 564d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu if (mFaceView != null) { 565d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.clear(); 566d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.setVisibility(View.VISIBLE); 567d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.setDisplayOrientation(orientation); 568d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.setMirror(mirror); 569d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.resume(); 570d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu } 571d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 572d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 573d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb @Override 5745a344964cb003525727c31d295ca3a592c245606Sol Boucher public void onFaceDetection(Face[] faces, CameraAgent.CameraProxy camera) { 575d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu if (mFaceView != null) { 576d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.setFaces(faces); 577d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu } 578d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 579d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 580d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb} 581