ActivityBase.java revision 1cc3a3466c8e9f30f13b81a88d8b2f31050c599c
14d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang/*
24d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * Copyright (C) 2009 The Android Open Source Project
34d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang *
44d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * Licensed under the Apache License, Version 2.0 (the "License");
54d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * you may not use this file except in compliance with the License.
64d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * You may obtain a copy of the License at
74d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang *
84d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang *      http://www.apache.org/licenses/LICENSE-2.0
94d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang *
104d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * Unless required by applicable law or agreed to in writing, software
114d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * distributed under the License is distributed on an "AS IS" BASIS,
124d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * See the License for the specific language governing permissions and
144d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * limitations under the License.
154d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang */
164d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang
174d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Changpackage com.android.camera;
184d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang
197d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Millerimport android.app.KeyguardManager;
20c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.content.ContentResolver;
21892781804513066b68b4a2fa6f846e862dac252aOwen Linimport android.content.Context;
225df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Liimport android.content.Intent;
234c7b291018e08dbb4bc1712d95117a294fa1416cWu-cheng Liimport android.content.pm.ActivityInfo;
24296d27772b9543d55820e1d24d900fea959f1b7aPin Tingimport android.hardware.Camera.Parameters;
25c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.os.AsyncTask;
268608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Changimport android.os.Bundle;
277d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Millerimport android.util.Log;
281cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Liimport android.view.animation.DecelerateInterpolator;
294c7b291018e08dbb4bc1712d95117a294fa1416cWu-cheng Liimport android.view.KeyEvent;
30c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.view.View;
31a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport android.view.Window;
32892781804513066b68b4a2fa6f846e862dac252aOwen Linimport android.view.WindowManager;
33892781804513066b68b4a2fa6f846e862dac252aOwen Lin
34892781804513066b68b4a2fa6f846e862dac252aOwen Linimport com.android.camera.ui.PopupManager;
35892781804513066b68b4a2fa6f846e862dac252aOwen Linimport com.android.camera.ui.RotateImageView;
36a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.app.AbstractGalleryActivity;
37a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.app.PhotoPage;
38a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.app.GalleryActionBar;
39a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.util.MediaSetUtils;
404d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang
41aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Liimport java.io.File;
42aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
4377c1cdc8f2cda250b1db842204efb49f87e094aeChih-Chung Chang/**
447673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li * Superclass of Camera and VideoCamera activities.
4577c1cdc8f2cda250b1db842204efb49f87e094aeChih-Chung Chang */
46a6b966047b6215b02c502a3f143106070abf6009Angus Kongabstract public class ActivityBase extends AbstractGalleryActivity
47a6b966047b6215b02c502a3f143106070abf6009Angus Kong        implements CameraScreenNail.PositionChangedListener {
48a6b966047b6215b02c502a3f143106070abf6009Angus Kong
497d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    private static final String TAG = "ActivityBase";
507d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    private static boolean LOGV = false;
515df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    private int mResultCodeForTesting;
527d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    private boolean mOnResumePending;
535df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    private Intent mResultDataForTesting;
544edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    private OnScreenHint mStorageHint;
551cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    private UpdateCameraAppView mUpdateCameraAppView;
561cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    private HideCameraAppView mHideCameraAppView;
57a6b966047b6215b02c502a3f143106070abf6009Angus Kong
58c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    // The bitmap of the last captured picture thumbnail and the URI of the
59c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    // original picture.
60c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected Thumbnail mThumbnail;
61c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    // An imageview showing showing the last captured picture thumbnail.
62c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected RotateImageView mThumbnailView;
638a674bebfba0c4dd4b01018276d20f198f65f19eWu-cheng Li    protected int mThumbnailViewWidth; // layout width of the thumbnail
64c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected AsyncTask<Void, Void, Thumbnail> mLoadThumbnailTask;
65475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected boolean mOpenCameraFail;
66475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected boolean mCameraDisabled;
67475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected CameraManager.CameraProxy mCameraDevice;
68296d27772b9543d55820e1d24d900fea959f1b7aPin Ting    protected Parameters mParameters;
699833a3328025552a3a176dc4d054cde63ef11885Wu-cheng Li    protected boolean mPaused; // The activity is paused.
70a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected GalleryActionBar mActionBar;
71475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting
72475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    // multiple cameras support
73475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected int mNumberOfCameras;
74475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected int mCameraId;
75475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting
76a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected CameraScreenNail mCameraScreenNail; // This shows camera preview.
77a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // The view containing only camera related widgets like control panel,
78a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // indicator bar, focus indicator and etc.
79a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected View mCameraAppView;
801cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    protected boolean mShowCameraAppView = true;
81a6b966047b6215b02c502a3f143106070abf6009Angus Kong
82475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected class CameraOpenThread extends Thread {
83475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        @Override
84475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        public void run() {
85475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            try {
86475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mCameraDevice = Util.openCamera(ActivityBase.this, mCameraId);
87296d27772b9543d55820e1d24d900fea959f1b7aPin Ting                mParameters = mCameraDevice.getParameters();
88475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            } catch (CameraHardwareException e) {
89475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mOpenCameraFail = true;
90475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            } catch (CameraDisabledException e) {
91475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mCameraDisabled = true;
92475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            }
93475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        }
94475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    }
955df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
964d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    @Override
978608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    public void onCreate(Bundle icicle) {
984c7b291018e08dbb4bc1712d95117a294fa1416cWu-cheng Li        if (Util.isTabletUI()) {
994c7b291018e08dbb4bc1712d95117a294fa1416cWu-cheng Li            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
100d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang        } else {
101d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
1024c7b291018e08dbb4bc1712d95117a294fa1416cWu-cheng Li        }
103a6b966047b6215b02c502a3f143106070abf6009Angus Kong        requestWindowFeature(Window.FEATURE_ACTION_BAR);
104a6b966047b6215b02c502a3f143106070abf6009Angus Kong        requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
105a6b966047b6215b02c502a3f143106070abf6009Angus Kong        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
106e5b6a36e64ef2c2cb1435c138a5fc179e9a6bc9aWu-cheng Li        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
1078608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang        super.onCreate(icicle);
108a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // The full screen mode might be turned off previously. Add the flag again.
109a6b966047b6215b02c502a3f143106070abf6009Angus Kong        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
110a6b966047b6215b02c502a3f143106070abf6009Angus Kong        mActionBar = new GalleryActionBar(this);
1118608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    }
1128608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang
1138608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    @Override
1147d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    public void onWindowFocusChanged(boolean hasFocus) {
1157d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        if (LOGV) Log.v(TAG, "onWindowFocusChanged.hasFocus=" + hasFocus
1167d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller                + ".mOnResumePending=" + mOnResumePending);
1177d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        if (hasFocus && mOnResumePending) {
1189833a3328025552a3a176dc4d054cde63ef11885Wu-cheng Li            mPaused = false;
1197d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller            doOnResume();
1207d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller            mOnResumePending = false;
1217d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        }
1227d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    }
1237d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
1247d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    @Override
1257d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    protected void onResume() {
1267d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        super.onResume();
1277d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        // Don't grab the camera if in use by lockscreen. For example, face
1287d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        // unlock may be using the camera. Camera may be already opened in
1297d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        // onCreate. doOnResume should continue if mCameraDevice != null.
1308853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li        // Suppose camera app is in the foreground. If users turn off and turn
1318853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li        // on the screen very fast, camera app can still have the focus when the
132475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        // lock screen shows up. The keyguard takes input focus, so the camera
1338853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li        // app will lose focus when it is displayed.
1348853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li        if (LOGV) Log.v(TAG, "onResume. hasWindowFocus()=" + hasWindowFocus());
1358853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li        if (mCameraDevice == null && isKeyguardLocked()) {
1368853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li            if (LOGV) Log.v(TAG, "onResume. mOnResumePending=true");
1377d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller            mOnResumePending = true;
1387d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        } else {
1398853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li            if (LOGV) Log.v(TAG, "onResume. mOnResumePending=false");
1409833a3328025552a3a176dc4d054cde63ef11885Wu-cheng Li            mPaused = false;
1417d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller            doOnResume();
1427d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller            mOnResumePending = false;
1437d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        }
1447d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    }
1457d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
1467d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    @Override
1477d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    protected void onPause() {
1489833a3328025552a3a176dc4d054cde63ef11885Wu-cheng Li        mPaused = true;
1497d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        if (LOGV) Log.v(TAG, "onPause");
150aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        saveThumbnailToFile();
1517d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        super.onPause();
1524edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong
153c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mLoadThumbnailTask != null) {
154c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask.cancel(true);
155c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask = null;
156c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
157c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
1584edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (mStorageHint != null) {
1594edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.cancel();
1604edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint = null;
1614edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
1624edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong
1637d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        mOnResumePending = false;
1647d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    }
1657d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
1667d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    // Put the code of onResume in this method.
1677d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    abstract protected void doOnResume();
1687d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
1697d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    @Override
1704d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    public boolean onSearchRequested() {
1714d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang        return false;
1724d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    }
1737673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li
1747673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    @Override
1757673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    public boolean onKeyDown(int keyCode, KeyEvent event) {
1767673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        // Prevent software keyboard or voice search from showing up.
1777673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        if (keyCode == KeyEvent.KEYCODE_SEARCH
1787673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li                || keyCode == KeyEvent.KEYCODE_MENU) {
1797673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li            if (event.isLongPress()) return true;
1807673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        }
1817673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li
1827673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        return super.onKeyDown(keyCode, event);
1837673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    }
1845df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1855df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    protected void setResultEx(int resultCode) {
1865df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultCodeForTesting = resultCode;
1875df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        setResult(resultCode);
1885df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
1895df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1905df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    protected void setResultEx(int resultCode, Intent data) {
1915df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultCodeForTesting = resultCode;
1925df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultDataForTesting = data;
1935df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        setResult(resultCode, data);
1945df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
1955df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1965df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    public int getResultCode() {
1975df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        return mResultCodeForTesting;
1985df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
1995df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
2005df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    public Intent getResultData() {
2015df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        return mResultDataForTesting;
2025df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
2035f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang
2045f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    @Override
2055f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    protected void onDestroy() {
2065f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang        PopupManager.removeInstance(this);
2075f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang        super.onDestroy();
2085f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    }
2097d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
2107d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    private boolean isKeyguardLocked() {
2117d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        KeyguardManager kgm = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
2128853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li        if (LOGV) {
2138853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li            if (kgm != null) {
2148853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li                Log.v(TAG, "kgm.isKeyguardLocked()="+kgm.isKeyguardLocked()
2158853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li                        + ". kgm.isKeyguardSecure()="+kgm.isKeyguardSecure());
2168853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li            }
2178853039421ae9b129ef40c8e71a347eac321d921Wu-cheng Li        }
2187d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        // isKeyguardSecure excludes the slide lock case.
2197d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        return (kgm != null) && kgm.isKeyguardLocked() && kgm.isKeyguardSecure();
2207d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    }
2214edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong
2224edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    protected void updateStorageHint(long storageSpace) {
2234edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        String message = null;
2244edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (storageSpace == Storage.UNAVAILABLE) {
2254edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.no_storage);
2264edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace == Storage.PREPARING) {
2274edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.preparing_sd);
2284edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace == Storage.UNKNOWN_SIZE) {
2294edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.access_sd_fail);
2304edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace < Storage.LOW_STORAGE_THRESHOLD) {
2314edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.spaceIsLow_content);
2324edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
2334edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong
2344edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (message != null) {
2354edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            if (mStorageHint == null) {
2364edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong                mStorageHint = OnScreenHint.makeText(this, message);
2374edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            } else {
2384edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong                mStorageHint.setText(message);
2394edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            }
2404edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.show();
2414edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (mStorageHint != null) {
2424edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.cancel();
2434edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint = null;
2444edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
2454edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    }
246c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
247c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    private void updateThumbnailView() {
248c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mThumbnail != null) {
249c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setBitmap(mThumbnail.getBitmap());
250c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setVisibility(View.VISIBLE);
251c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        } else {
252c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setBitmap(null);
253c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setVisibility(View.GONE);
254c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
255c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
256c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
257c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected void getLastThumbnail() {
258c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        mThumbnail = ThumbnailHolder.getLastThumbnail(getContentResolver());
259c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // Suppose users tap the thumbnail view, go to the gallery, delete the
260c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // image, and coming back to the camera. Thumbnail file will be invalid.
261c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // Since the new thumbnail will be loaded in another thread later, the
262c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // view should be set to gone to prevent from opening the invalid image.
263c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        updateThumbnailView();
264c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mThumbnail == null) {
265c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask = new LoadThumbnailTask().execute();
266c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
267c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
268c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
269aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    private class LoadThumbnailTask extends AsyncTask<Void, Void, Thumbnail> {
270c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        @Override
271c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        protected Thumbnail doInBackground(Void... params) {
272c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            // Load the thumbnail from the file.
273c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            ContentResolver resolver = getContentResolver();
274c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            Thumbnail t = Thumbnail.getLastThumbnailFromFile(getFilesDir(), resolver);
275c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
276c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            if (isCancelled()) return null;
277c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
278c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            if (t == null) {
279c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li                // Load the thumbnail from the media provider.
280c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li                t = Thumbnail.getLastThumbnailFromContentResolver(resolver);
281c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            }
282c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            return t;
283c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
284c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
285c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        @Override
286c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        protected void onPostExecute(Thumbnail thumbnail) {
287c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnail = thumbnail;
288c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            updateThumbnailView();
289c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
290c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
291aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
2926899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting    protected void gotoGallery() {
2936899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting        Util.viewUri(mThumbnail.getUri(), this);
2946899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting    }
2956899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting
296aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    protected void saveThumbnailToFile() {
297aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        if (mThumbnail != null && !mThumbnail.fromFile()) {
298aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            new SaveThumbnailTask().execute(mThumbnail);
299aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        }
300aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    }
301aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
302aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    private class SaveThumbnailTask extends AsyncTask<Thumbnail, Void, Void> {
303aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        @Override
304aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        protected Void doInBackground(Thumbnail... params) {
305aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            final int n = params.length;
306aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            final File filesDir = getFilesDir();
307aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            for (int i = 0; i < n; i++) {
308aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li                params[i].saveLastThumbnailToFile(filesDir);
309aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            }
310aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            return null;
311aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        }
312aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    }
313a6b966047b6215b02c502a3f143106070abf6009Angus Kong
314a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // Call this after setContentView.
315a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected void createCameraScreenNail(boolean getPictures) {
316a6b966047b6215b02c502a3f143106070abf6009Angus Kong        mCameraAppView = findViewById(R.id.camera_app_root);
317a6b966047b6215b02c502a3f143106070abf6009Angus Kong        Bundle data = new Bundle();
318a6b966047b6215b02c502a3f143106070abf6009Angus Kong        String path = "/local/all/";
319a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // Intent mode does not show camera roll. Use 0 as a work around for
320a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // invalid bucket id.
321a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // TODO: add support of empty media set in gallery.
322a6b966047b6215b02c502a3f143106070abf6009Angus Kong        path += (getPictures ? MediaSetUtils.CAMERA_BUCKET_ID : "0");
323a6b966047b6215b02c502a3f143106070abf6009Angus Kong        data.putString(PhotoPage.KEY_MEDIA_SET_PATH, path);
324a6b966047b6215b02c502a3f143106070abf6009Angus Kong        data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, path);
325a6b966047b6215b02c502a3f143106070abf6009Angus Kong
326a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // Send a CameraScreenNail to gallery to enable the camera preview.
327a6b966047b6215b02c502a3f143106070abf6009Angus Kong        CameraScreenNailHolder holder = new CameraScreenNailHolder(this);
328a6b966047b6215b02c502a3f143106070abf6009Angus Kong        data.putParcelable(PhotoPage.KEY_SCREENNAIL_HOLDER, holder);
329a6b966047b6215b02c502a3f143106070abf6009Angus Kong        getStateManager().startState(PhotoPage.class, data);
330a6b966047b6215b02c502a3f143106070abf6009Angus Kong        mCameraScreenNail = holder.getCameraScreenNail();
331a6b966047b6215b02c502a3f143106070abf6009Angus Kong        mCameraScreenNail.setPositionChangedListener(this);
332a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
333a6b966047b6215b02c502a3f143106070abf6009Angus Kong
3341cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    private class HideCameraAppView implements Runnable {
3351cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        @Override
3361cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        public void run() {
3371cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            mCameraAppView.setVisibility(View.GONE);
3381cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        }
3391cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    }
340a6b966047b6215b02c502a3f143106070abf6009Angus Kong    private class UpdateCameraAppView implements Runnable {
341a6b966047b6215b02c502a3f143106070abf6009Angus Kong        @Override
342a6b966047b6215b02c502a3f143106070abf6009Angus Kong        public void run() {
3431cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            if (mShowCameraAppView) {
344a6b966047b6215b02c502a3f143106070abf6009Angus Kong                mCameraAppView.setVisibility(View.VISIBLE);
3451cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                mCameraAppView.animate().withLayer().alpha(1);
3461cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            } else {
3471cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                mCameraAppView.animate().withLayer().alpha(0).withEndAction(mHideCameraAppView);
348a6b966047b6215b02c502a3f143106070abf6009Angus Kong            }
349a6b966047b6215b02c502a3f143106070abf6009Angus Kong        }
350a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
351a6b966047b6215b02c502a3f143106070abf6009Angus Kong
352a6b966047b6215b02c502a3f143106070abf6009Angus Kong    @Override
3531cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    public void onPositionChanged(int x, int y, int width, int height, boolean visible) {
354a6b966047b6215b02c502a3f143106070abf6009Angus Kong        if (!mPaused && !isFinishing()) {
3551cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            View rootView = (View) getGLRoot();
3561cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            int rootWidth = rootView.getWidth();
3571cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            int rootHeight = rootView.getHeight();
3581cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            boolean showCameraAppView;
3591cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            // Check if the camera preview is in the center.
3601cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            if (visible && (x == 0 && width == rootWidth) ||
3611cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                    (y == 0 && height == rootHeight && Math.abs(x - (rootWidth - width) / 2) <= 1)) {
3621cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                showCameraAppView = true;
363a6b966047b6215b02c502a3f143106070abf6009Angus Kong            } else {
3641cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                showCameraAppView = false;
3651cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            }
3661cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li
3671cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            if (mShowCameraAppView != showCameraAppView) {
3681cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                mShowCameraAppView = showCameraAppView;
3691cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                // Initialize the animation.
3701cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                if (mUpdateCameraAppView == null) {
3711cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                    mUpdateCameraAppView = new UpdateCameraAppView();
3721cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                    mHideCameraAppView = new HideCameraAppView();
3731cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                    mCameraAppView.animate().setDuration(300)
3741cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                            .setInterpolator(new DecelerateInterpolator());
3751cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                }
3761cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                runOnUiThread(mUpdateCameraAppView);
377a6b966047b6215b02c502a3f143106070abf6009Angus Kong            }
378a6b966047b6215b02c502a3f143106070abf6009Angus Kong        }
379a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
380a6b966047b6215b02c502a3f143106070abf6009Angus Kong
381a6b966047b6215b02c502a3f143106070abf6009Angus Kong    @Override
382a6b966047b6215b02c502a3f143106070abf6009Angus Kong    public GalleryActionBar getGalleryActionBar() {
383a6b966047b6215b02c502a3f143106070abf6009Angus Kong        return mActionBar;
384a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
3854d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang}
386