ActivityBase.java revision e14d9149a501183d3b785f4f4aa484c4b85192d1
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
19b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Changimport android.content.BroadcastReceiver;
20c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.content.ContentResolver;
21b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Changimport android.content.Context;
225df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Liimport android.content.Intent;
23b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Changimport android.content.IntentFilter;
24c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Liimport android.graphics.Bitmap;
25195f07f83be795b2dfc0cdd12636a2eb4afedd86Wu-cheng Liimport android.graphics.BitmapFactory;
2678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Changimport android.graphics.Rect;
27296d27772b9543d55820e1d24d900fea959f1b7aPin Tingimport android.hardware.Camera.Parameters;
2888e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Liimport android.net.Uri;
29c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.os.AsyncTask;
308608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Changimport android.os.Bundle;
31844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescuimport android.os.Handler;
32844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescuimport android.os.Message;
33b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Changimport android.support.v4.content.LocalBroadcastManager;
347d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Millerimport android.util.Log;
354c7b291018e08dbb4bc1712d95117a294fa1416cWu-cheng Liimport android.view.KeyEvent;
36c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.view.View;
37a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport android.view.Window;
38892781804513066b68b4a2fa6f846e862dac252aOwen Linimport android.view.WindowManager;
39525667ff4b93a577298085fe45660a2d15b0bd06Angus Kongimport android.view.animation.AlphaAnimation;
40525667ff4b93a577298085fe45660a2d15b0bd06Angus Kongimport android.view.animation.Animation;
41a029bd9976ebb618f321e8740c86b0f5d681d241Owen Linimport android.view.animation.DecelerateInterpolator;
42892781804513066b68b4a2fa6f846e862dac252aOwen Lin
43d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Liimport com.android.camera.ui.CameraPicker;
44525667ff4b93a577298085fe45660a2d15b0bd06Angus Kongimport com.android.camera.ui.LayoutChangeNotifier;
45892781804513066b68b4a2fa6f846e862dac252aOwen Linimport com.android.camera.ui.PopupManager;
46892781804513066b68b4a2fa6f846e862dac252aOwen Linimport com.android.camera.ui.RotateImageView;
47a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.app.AbstractGalleryActivity;
4878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Changimport com.android.gallery3d.app.AppBridge;
49a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.app.GalleryActionBar;
50a029bd9976ebb618f321e8740c86b0f5d681d241Owen Linimport com.android.gallery3d.app.PhotoPage;
51c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Liimport com.android.gallery3d.common.ApiHelper;
5278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Changimport com.android.gallery3d.ui.ScreenNail;
53a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.util.MediaSetUtils;
544d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang
55aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Liimport java.io.File;
56aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
5777c1cdc8f2cda250b1db842204efb49f87e094aeChih-Chung Chang/**
587673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li * Superclass of Camera and VideoCamera activities.
5977c1cdc8f2cda250b1db842204efb49f87e094aeChih-Chung Chang */
60525667ff4b93a577298085fe45660a2d15b0bd06Angus Kongpublic abstract class ActivityBase extends AbstractGalleryActivity
61525667ff4b93a577298085fe45660a2d15b0bd06Angus Kong        implements LayoutChangeNotifier.Listener {
62a6b966047b6215b02c502a3f143106070abf6009Angus Kong
637d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    private static final String TAG = "ActivityBase";
64c38faeb66a3f2cc96e4c5e951228d9b01e12edb3Chih-Chung Chang    private static final int CAMERA_APP_VIEW_TOGGLE_TIME = 100;  // milliseconds
65b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    private static final String ACTION_DELETE_PICTURE =
66b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            "com.android.gallery3d.action.DELETE_PICTURE";
6788e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    private static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE =
6888e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li            "android.media.action.STILL_IMAGE_CAMERA_SECURE";
6953b11253fde509b01851ba022d9178c7c6f13ddeWu-cheng Li    public static final String ACTION_IMAGE_CAPTURE_SECURE =
70ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li            "android.media.action.IMAGE_CAPTURE_SECURE";
7188e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    // The intent extra for camera from secure lock screen. True if the gallery
7288e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    // should only show newly captured pictures. sSecureAlbumId does not
7388e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    // increment. This is used when switching between camera, camcorder, and
7488e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    // panorama. If the extra is not set, it is in the normal camera mode.
7588e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    public static final String SECURE_CAMERA_EXTRA = "secure_camera";
7647a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang
775df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    private int mResultCodeForTesting;
785df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    private Intent mResultDataForTesting;
794edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    private OnScreenHint mStorageHint;
80bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    private View mSingleTapArea;
81a6b966047b6215b02c502a3f143106070abf6009Angus Kong
82c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    // The bitmap of the last captured picture thumbnail and the URI of the
83c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    // original picture.
84c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected Thumbnail mThumbnail;
858a674bebfba0c4dd4b01018276d20f198f65f19eWu-cheng Li    protected int mThumbnailViewWidth; // layout width of the thumbnail
86c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected AsyncTask<Void, Void, Thumbnail> mLoadThumbnailTask;
87d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    // An imageview showing the last captured picture thumbnail.
88d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    protected RotateImageView mThumbnailView;
89d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    protected CameraPicker mCameraPicker;
90d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li
91475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected boolean mOpenCameraFail;
92475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected boolean mCameraDisabled;
93475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected CameraManager.CameraProxy mCameraDevice;
94296d27772b9543d55820e1d24d900fea959f1b7aPin Ting    protected Parameters mParameters;
955c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li    // The activity is paused. The classes that extend this class should set
965c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li    // mPaused the first thing in onResume/onPause.
975c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li    protected boolean mPaused;
98a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected GalleryActionBar mActionBar;
99475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting
100475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    // multiple cameras support
101475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected int mNumberOfCameras;
102475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected int mCameraId;
103d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    // The activity is going to switch to the specified camera id. This is
104d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    // needed because texture copy is done in GL thread. -1 means camera is not
105d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    // switching.
106d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    protected int mPendingSwitchCameraId = -1;
107475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting
10878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    protected MyAppBridge mAppBridge;
109c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li    protected ScreenNail mCameraScreenNail; // This shows camera preview.
110a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // The view containing only camera related widgets like control panel,
111a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // indicator bar, focus indicator and etc.
112a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected View mCameraAppView;
1131cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    protected boolean mShowCameraAppView = true;
11447a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang    private Animation mCameraAppViewFadeIn;
11547a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang    private Animation mCameraAppViewFadeOut;
11688e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    // Secure album id. This should be incremented every time the camera is
11788e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    // launched from the secure lock screen. The id should be the same when
11888e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    // switching between camera, camcorder, and panorama.
11988e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    protected static int sSecureAlbumId;
120ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li    // True if the camera is started from secure lock screen.
12188e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    protected boolean mSecureCamera;
1227717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li    private static boolean sFirstStartAfterScreenOn = true;
12347a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang
124844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    private long mStorageSpace = Storage.LOW_STORAGE_THRESHOLD;
125844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    private static final int UPDATE_STORAGE_HINT = 0;
126844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    private final Handler mHandler = new Handler() {
127844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu            @Override
128844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu            public void handleMessage(Message msg) {
129844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu                switch (msg.what) {
130844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu                    case UPDATE_STORAGE_HINT:
131844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu                        updateStorageHint();
132844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu                        return;
133844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu                }
134844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu            }
135844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    };
136844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu
137844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
138844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        @Override
139844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        public void onReceive(Context context, Intent intent) {
140844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu            String action = intent.getAction();
141844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu            if (action.equals(Intent.ACTION_MEDIA_MOUNTED)
142844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu                    || action.equals(Intent.ACTION_MEDIA_UNMOUNTED)
143844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu                    || action.equals(Intent.ACTION_MEDIA_CHECKING)
144844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu                    || action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) {
145844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu                updateStorageSpaceAndHint();
146844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu            }
147844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        }
148844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    };
149844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu
150b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    private boolean mUpdateThumbnailDelayed;
151b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    private IntentFilter mDeletePictureFilter =
152b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            new IntentFilter(ACTION_DELETE_PICTURE);
153b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    private BroadcastReceiver mDeletePictureReceiver =
154b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            new BroadcastReceiver() {
155b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                @Override
156b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                public void onReceive(Context context, Intent intent) {
157b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                    if (mShowCameraAppView) {
158b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        getLastThumbnailUncached();
159b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                    } else {
160b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        mUpdateThumbnailDelayed = true;
161b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                    }
162b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                }
163b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            };
164a6b966047b6215b02c502a3f143106070abf6009Angus Kong
165d80b2cd48dd5958a0e9f370ce28c483b3a1dd166Wu-cheng Li    // close activity when screen turns off
166d80b2cd48dd5958a0e9f370ce28c483b3a1dd166Wu-cheng Li    private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
167d80b2cd48dd5958a0e9f370ce28c483b3a1dd166Wu-cheng Li        @Override
168d80b2cd48dd5958a0e9f370ce28c483b3a1dd166Wu-cheng Li        public void onReceive(Context context, Intent intent) {
169d80b2cd48dd5958a0e9f370ce28c483b3a1dd166Wu-cheng Li            finish();
170d80b2cd48dd5958a0e9f370ce28c483b3a1dd166Wu-cheng Li        }
171d80b2cd48dd5958a0e9f370ce28c483b3a1dd166Wu-cheng Li    };
172d80b2cd48dd5958a0e9f370ce28c483b3a1dd166Wu-cheng Li
1737717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li    private static BroadcastReceiver sScreenOffReceiver;
1747717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li    private static class ScreenOffReceiver extends BroadcastReceiver {
1757717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li        @Override
1767717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li        public void onReceive(Context context, Intent intent) {
1777717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li            sFirstStartAfterScreenOn = true;
1787717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li        }
1797717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li    }
1807717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li
1817717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li    public static boolean isFirstStartAfterScreenOn() {
1827717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li        return sFirstStartAfterScreenOn;
1837717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li    }
1847717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li
1857717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li    public static void resetFirstStartAfterScreenOn() {
1867717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li        sFirstStartAfterScreenOn = false;
1877717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li    }
1887717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li
189475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected class CameraOpenThread extends Thread {
190475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        @Override
191475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        public void run() {
192475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            try {
193475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mCameraDevice = Util.openCamera(ActivityBase.this, mCameraId);
194296d27772b9543d55820e1d24d900fea959f1b7aPin Ting                mParameters = mCameraDevice.getParameters();
195475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            } catch (CameraHardwareException e) {
196475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mOpenCameraFail = true;
197475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            } catch (CameraDisabledException e) {
198475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mCameraDisabled = true;
199475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            }
200475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        }
201475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    }
2025df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
2034d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    @Override
2048608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    public void onCreate(Bundle icicle) {
2056a4a72b643929701c5d7c8b68b91d762c7277c20Wu-cheng Li        super.disableToggleStatusBar();
206a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // Set a theme with action bar. It is not specified in manifest because
207a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // we want to hide it by default. setTheme must happen before
208a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // setContentView.
209a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        //
210a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // This must be set before we call super.onCreate(), where the window's
211a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // background is removed.
212a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        setTheme(R.style.Theme_Gallery);
213a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
214ae8b4eecd123aae8593b620b9e0783a03a907a98Ahbong Chang        if (ApiHelper.HAS_ACTION_BAR) {
215ae8b4eecd123aae8593b620b9e0783a03a907a98Ahbong Chang            requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
216ae8b4eecd123aae8593b620b9e0783a03a907a98Ahbong Chang        } else {
217ae8b4eecd123aae8593b620b9e0783a03a907a98Ahbong Chang            requestWindowFeature(Window.FEATURE_NO_TITLE);
218ae8b4eecd123aae8593b620b9e0783a03a907a98Ahbong Chang        }
219a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin
22088e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li        // Check if this is in the secure camera mode.
22188e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li        Intent intent = getIntent();
222ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li        String action = intent.getAction();
223ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li        if (INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(action)) {
22488e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li            mSecureCamera = true;
22588e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li            // Use a new album when this is started from the lock screen.
22688e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li            sSecureAlbumId++;
227ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li        } else if (ACTION_IMAGE_CAPTURE_SECURE.equals(action)) {
228ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li            mSecureCamera = true;
22988e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li        } else {
23088e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li            mSecureCamera = intent.getBooleanExtra(SECURE_CAMERA_EXTRA, false);
23188e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li        }
232d80b2cd48dd5958a0e9f370ce28c483b3a1dd166Wu-cheng Li        if (mSecureCamera) {
2337717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li            IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
2347717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li            registerReceiver(mScreenOffReceiver, filter);
2357717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li            if (sScreenOffReceiver == null) {
2367717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li                sScreenOffReceiver = new ScreenOffReceiver();
2377717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li                getApplicationContext().registerReceiver(sScreenOffReceiver, filter);
2387717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li            }
239d80b2cd48dd5958a0e9f370ce28c483b3a1dd166Wu-cheng Li        }
2408608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang        super.onCreate(icicle);
2418608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    }
2428608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang
24305e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong    public boolean isPanoramaActivity() {
24405e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong        return false;
24505e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong    }
24605e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong
2478608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    @Override
248b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    protected void onResume() {
249b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        super.onResume();
250b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this);
251b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        manager.registerReceiver(mDeletePictureReceiver, mDeletePictureFilter);
252844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu
253844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        installIntentFilter();
254844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        if(updateStorageHintOnResume()) {
255844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu            updateStorageSpace();
256844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu            mHandler.sendEmptyMessageDelayed(UPDATE_STORAGE_HINT, 200);
257844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        }
258b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    }
259b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang
260b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    @Override
2617d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    protected void onPause() {
2625c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li        super.onPause();
263b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this);
264b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        manager.unregisterReceiver(mDeletePictureReceiver);
265b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang
266aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        saveThumbnailToFile();
2674edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong
268c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mLoadThumbnailTask != null) {
269c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask.cancel(true);
270c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask = null;
271c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
272c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
2734edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (mStorageHint != null) {
2744edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.cancel();
2754edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint = null;
2764edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
277844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu
278844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        unregisterReceiver(mReceiver);
2797d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    }
2807d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
2817d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    @Override
28272fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li    public void setContentView(int layoutResID) {
28372fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        super.setContentView(layoutResID);
28472fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        // getActionBar() should be after setContentView
28572fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        mActionBar = new GalleryActionBar(this);
28672fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        mActionBar.hide();
28772fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li    }
28872fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li
28972fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li    @Override
2904d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    public boolean onSearchRequested() {
2914d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang        return false;
2924d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    }
2937673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li
2947673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    @Override
2957673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    public boolean onKeyDown(int keyCode, KeyEvent event) {
2967673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        // Prevent software keyboard or voice search from showing up.
2977673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        if (keyCode == KeyEvent.KEYCODE_SEARCH
2987673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li                || keyCode == KeyEvent.KEYCODE_MENU) {
2997673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li            if (event.isLongPress()) return true;
3007673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        }
3010703fec905d13cff403955fdffdd99b1ce17113fBobby Georgescu        if (keyCode == KeyEvent.KEYCODE_MENU && mShowCameraAppView) {
3020703fec905d13cff403955fdffdd99b1ce17113fBobby Georgescu            return true;
3030703fec905d13cff403955fdffdd99b1ce17113fBobby Georgescu        }
3047673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li
3057673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        return super.onKeyDown(keyCode, event);
3067673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    }
3075df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
3080703fec905d13cff403955fdffdd99b1ce17113fBobby Georgescu    @Override
3090703fec905d13cff403955fdffdd99b1ce17113fBobby Georgescu    public boolean onKeyUp(int keyCode, KeyEvent event) {
3100703fec905d13cff403955fdffdd99b1ce17113fBobby Georgescu        if (keyCode == KeyEvent.KEYCODE_MENU && mShowCameraAppView) {
3110703fec905d13cff403955fdffdd99b1ce17113fBobby Georgescu            return true;
3120703fec905d13cff403955fdffdd99b1ce17113fBobby Georgescu        }
3130703fec905d13cff403955fdffdd99b1ce17113fBobby Georgescu        return super.onKeyUp(keyCode, event);
3140703fec905d13cff403955fdffdd99b1ce17113fBobby Georgescu    }
3150703fec905d13cff403955fdffdd99b1ce17113fBobby Georgescu
3165df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    protected void setResultEx(int resultCode) {
3175df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultCodeForTesting = resultCode;
3185df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        setResult(resultCode);
3195df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
3205df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
3215df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    protected void setResultEx(int resultCode, Intent data) {
3225df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultCodeForTesting = resultCode;
3235df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultDataForTesting = data;
3245df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        setResult(resultCode, data);
3255df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
3265df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
3275df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    public int getResultCode() {
3285df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        return mResultCodeForTesting;
3295df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
3305df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
3315df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    public Intent getResultData() {
3325df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        return mResultDataForTesting;
3335df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
3345f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang
3355f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    @Override
3365f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    protected void onDestroy() {
3375f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang        PopupManager.removeInstance(this);
338d80b2cd48dd5958a0e9f370ce28c483b3a1dd166Wu-cheng Li        if (mSecureCamera) unregisterReceiver(mScreenOffReceiver);
3395f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang        super.onDestroy();
3405f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    }
3417d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
342844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    protected void installIntentFilter() {
343844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        // install an intent filter to receive SD card related events.
344844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        IntentFilter intentFilter =
345844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu                new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
346844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
347844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
348844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        intentFilter.addAction(Intent.ACTION_MEDIA_CHECKING);
349844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        intentFilter.addDataScheme("file");
350844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        registerReceiver(mReceiver, intentFilter);
351844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    }
352844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu
353844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    protected void updateStorageSpace() {
354844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        mStorageSpace = Storage.getAvailableSpace();
355844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    }
356844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu
357844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    protected long getStorageSpace() {
358844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        return mStorageSpace;
359844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    }
360844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu
361844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    protected void updateStorageSpaceAndHint() {
362844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        updateStorageSpace();
363844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        updateStorageHint(mStorageSpace);
364844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    }
365844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu
366844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    protected void updateStorageHint() {
367844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        updateStorageHint(mStorageSpace);
368844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    }
369844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu
370844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    protected boolean updateStorageHintOnResume() {
371844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        return true;
372844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu    }
373844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu
3744edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    protected void updateStorageHint(long storageSpace) {
3754edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        String message = null;
3764edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (storageSpace == Storage.UNAVAILABLE) {
3774edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.no_storage);
3784edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace == Storage.PREPARING) {
3794edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.preparing_sd);
3804edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace == Storage.UNKNOWN_SIZE) {
3814edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.access_sd_fail);
382844d5d3043103f968beb77a6aa857d5f904d8fccBobby Georgescu        } else if (storageSpace <= Storage.LOW_STORAGE_THRESHOLD) {
3834edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.spaceIsLow_content);
3844edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
3854edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong
3864edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (message != null) {
3874edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            if (mStorageHint == null) {
3884edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong                mStorageHint = OnScreenHint.makeText(this, message);
3894edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            } else {
3904edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong                mStorageHint.setText(message);
3914edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            }
3924edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.show();
3934edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (mStorageHint != null) {
3944edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.cancel();
3954edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint = null;
3964edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
3974edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    }
398c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
399a0b7c6b3c61b68db7f4eb33d81c886fb4e095f2cPin Ting    protected void updateThumbnailView() {
400d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        if (mThumbnail != null && mThumbnailView != null) {
401c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setBitmap(mThumbnail.getBitmap());
402c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setVisibility(View.VISIBLE);
403d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        } else if (mThumbnailView != null) {
404c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setBitmap(null);
405c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setVisibility(View.GONE);
406c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
407c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
408c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
409c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected void getLastThumbnail() {
410c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        mThumbnail = ThumbnailHolder.getLastThumbnail(getContentResolver());
411c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // Suppose users tap the thumbnail view, go to the gallery, delete the
412c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // image, and coming back to the camera. Thumbnail file will be invalid.
413c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // Since the new thumbnail will be loaded in another thread later, the
414c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // view should be set to gone to prevent from opening the invalid image.
415c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        updateThumbnailView();
416c1f6c073113e20fd0dbeae6d26dcc651c9049fd7Wu-cheng Li        if (mThumbnail == null && !mSecureCamera) {
417b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            mLoadThumbnailTask = new LoadThumbnailTask(true).execute();
418c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
419c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
420c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
421b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    protected void getLastThumbnailUncached() {
422c1f6c073113e20fd0dbeae6d26dcc651c9049fd7Wu-cheng Li        if (mSecureCamera) {
423c1f6c073113e20fd0dbeae6d26dcc651c9049fd7Wu-cheng Li            // Check if the thumbnail is valid.
424c1f6c073113e20fd0dbeae6d26dcc651c9049fd7Wu-cheng Li            if (mThumbnail != null && !Util.isUriValid(
425c1f6c073113e20fd0dbeae6d26dcc651c9049fd7Wu-cheng Li                    mThumbnail.getUri(), getContentResolver())) {
426c1f6c073113e20fd0dbeae6d26dcc651c9049fd7Wu-cheng Li                mThumbnail = null;
427c1f6c073113e20fd0dbeae6d26dcc651c9049fd7Wu-cheng Li                updateThumbnailView();
428c1f6c073113e20fd0dbeae6d26dcc651c9049fd7Wu-cheng Li            }
429c1f6c073113e20fd0dbeae6d26dcc651c9049fd7Wu-cheng Li        } else {
430c1f6c073113e20fd0dbeae6d26dcc651c9049fd7Wu-cheng Li            if (mLoadThumbnailTask != null) mLoadThumbnailTask.cancel(true);
431c1f6c073113e20fd0dbeae6d26dcc651c9049fd7Wu-cheng Li            mLoadThumbnailTask = new LoadThumbnailTask(false).execute();
432c1f6c073113e20fd0dbeae6d26dcc651c9049fd7Wu-cheng Li        }
433b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    }
434b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang
435aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    private class LoadThumbnailTask extends AsyncTask<Void, Void, Thumbnail> {
436b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        private boolean mLookAtCache;
437b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang
438b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        public LoadThumbnailTask(boolean lookAtCache) {
439b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            mLookAtCache = lookAtCache;
440b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        }
441b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang
442c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        @Override
443c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        protected Thumbnail doInBackground(Void... params) {
444c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            // Load the thumbnail from the file.
445c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            ContentResolver resolver = getContentResolver();
446b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            Thumbnail t = null;
447b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            if (mLookAtCache) {
448b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                t = Thumbnail.getLastThumbnailFromFile(getFilesDir(), resolver);
449b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            }
450c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
451c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            if (isCancelled()) return null;
452c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
453c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            if (t == null) {
454b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                Thumbnail result[] = new Thumbnail[1];
455c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li                // Load the thumbnail from the media provider.
456b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                int code = Thumbnail.getLastThumbnailFromContentResolver(
457b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        resolver, result);
458b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                switch (code) {
459b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                    case Thumbnail.THUMBNAIL_FOUND:
460b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        return result[0];
461b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                    case Thumbnail.THUMBNAIL_NOT_FOUND:
462b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        return null;
463b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                    case Thumbnail.THUMBNAIL_DELETED:
464b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        cancel(true);
465b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        return null;
466b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                }
467c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            }
468c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            return t;
469c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
470c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
471c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        @Override
472c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        protected void onPostExecute(Thumbnail thumbnail) {
473b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            if (isCancelled()) return;
474c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnail = thumbnail;
475c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            updateThumbnailView();
476c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
477c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
478aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
4796899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting    protected void gotoGallery() {
480252da3c55a35c77fa4be4d51f79dac4aaf7cdb77Pin Ting        // Move the next picture with capture animation. "1" means next.
481252da3c55a35c77fa4be4d51f79dac4aaf7cdb77Pin Ting        mAppBridge.switchWithCaptureAnimation(1);
4826899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting    }
4836899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting
484aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    protected void saveThumbnailToFile() {
485aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        if (mThumbnail != null && !mThumbnail.fromFile()) {
486aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            new SaveThumbnailTask().execute(mThumbnail);
487aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        }
488aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    }
489aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
490aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    private class SaveThumbnailTask extends AsyncTask<Thumbnail, Void, Void> {
491aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        @Override
492aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        protected Void doInBackground(Thumbnail... params) {
493aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            final int n = params.length;
494aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            final File filesDir = getFilesDir();
495aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            for (int i = 0; i < n; i++) {
496aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li                params[i].saveLastThumbnailToFile(filesDir);
497aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            }
498aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            return null;
499aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        }
500aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    }
501a6b966047b6215b02c502a3f143106070abf6009Angus Kong
502a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // Call this after setContentView.
503e14d9149a501183d3b785f4f4aa484c4b85192d1George Mount    public ScreenNail createCameraScreenNail(boolean getPictures) {
504a6b966047b6215b02c502a3f143106070abf6009Angus Kong        mCameraAppView = findViewById(R.id.camera_app_root);
505a6b966047b6215b02c502a3f143106070abf6009Angus Kong        Bundle data = new Bundle();
50688e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li        String path;
507ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li        if (getPictures) {
508ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li            if (mSecureCamera) {
509ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li                path = "/secure/all/" + sSecureAlbumId;
510ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li            } else {
511ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li                path = "/local/all/" + MediaSetUtils.CAMERA_BUCKET_ID;
512ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li            }
51388e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li        } else {
514ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li            path = "/local/all/0"; // Use 0 so gallery does not show anything.
51588e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li        }
516a6b966047b6215b02c502a3f143106070abf6009Angus Kong        data.putString(PhotoPage.KEY_MEDIA_SET_PATH, path);
517a6b966047b6215b02c502a3f143106070abf6009Angus Kong        data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, path);
518ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li        data.putBoolean(PhotoPage.KEY_SHOW_WHEN_LOCKED, mSecureCamera);
519a6b966047b6215b02c502a3f143106070abf6009Angus Kong
52078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // Send an AppBridge to gallery to enable the camera preview.
52178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        mAppBridge = new MyAppBridge();
52278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        data.putParcelable(PhotoPage.KEY_APP_BRIDGE, mAppBridge);
5238e887b3911f3c182011c20d709832755d96a5959Doris Liu        if (getStateManager().getStateCount() == 0) {
5248e887b3911f3c182011c20d709832755d96a5959Doris Liu            getStateManager().startState(PhotoPage.class, data);
5258e887b3911f3c182011c20d709832755d96a5959Doris Liu        } else {
5268e887b3911f3c182011c20d709832755d96a5959Doris Liu            getStateManager().switchState(getStateManager().getTopState(),
5278e887b3911f3c182011c20d709832755d96a5959Doris Liu                    PhotoPage.class, data);
5288e887b3911f3c182011c20d709832755d96a5959Doris Liu        }
52978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        mCameraScreenNail = mAppBridge.getCameraScreenNail();
530e14d9149a501183d3b785f4f4aa484c4b85192d1George Mount        return mCameraScreenNail;
531a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
532a6b966047b6215b02c502a3f143106070abf6009Angus Kong
533d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb    // Call this after setContentView.
534e14d9149a501183d3b785f4f4aa484c4b85192d1George Mount    protected ScreenNail reuseCameraScreenNail(boolean getPictures) {
535d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        mCameraAppView = findViewById(R.id.camera_app_root);
536d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        Bundle data = new Bundle();
537d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        String path;
538ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li        if (getPictures) {
539ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li            if (mSecureCamera) {
540ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li                path = "/secure/all/" + sSecureAlbumId;
541ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li            } else {
542ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li                path = "/local/all/" + MediaSetUtils.CAMERA_BUCKET_ID;
543ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li            }
544d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        } else {
545ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li            path = "/local/all/0"; // Use 0 so gallery does not show anything.
546d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        }
547d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        data.putString(PhotoPage.KEY_MEDIA_SET_PATH, path);
548d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, path);
549ce51afce8c74f2c68e386b2a8f35c4be6772b760Wu-cheng Li        data.putBoolean(PhotoPage.KEY_SHOW_WHEN_LOCKED, mSecureCamera);
550d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb
551d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        // Send an AppBridge to gallery to enable the camera preview.
552d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        if (mAppBridge == null) {
553d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb            mAppBridge = new MyAppBridge();
554d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        }
555d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        data.putParcelable(PhotoPage.KEY_APP_BRIDGE, mAppBridge);
556d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        if (getStateManager().getStateCount() == 0) {
557d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb            getStateManager().startState(PhotoPage.class, data);
558d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        }
559d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb        mCameraScreenNail = mAppBridge.getCameraScreenNail();
560e14d9149a501183d3b785f4f4aa484c4b85192d1George Mount        return mCameraScreenNail;
561d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb    }
562d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb
56347a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang    private class HideCameraAppView implements Animation.AnimationListener {
5641cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        @Override
56547a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        public void onAnimationEnd(Animation animation) {
566f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            // We cannot set this as GONE because we want to receive the
567f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            // onLayoutChange() callback even when we are invisible.
568f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            mCameraAppView.setVisibility(View.INVISIBLE);
5691cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        }
57047a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang
57147a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        @Override
57247a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        public void onAnimationRepeat(Animation animation) {
57347a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        }
57447a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang
57547a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        @Override
57647a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        public void onAnimationStart(Animation animation) {
57747a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        }
5781cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    }
57978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
580c94cd4a5206b05541de0dc8a4821c64d0edba352Angus Kong    protected void updateCameraAppView() {
58147a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        // Initialize the animation.
58247a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        if (mCameraAppViewFadeIn == null) {
58347a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeIn = new AlphaAnimation(0f, 1f);
58447a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeIn.setDuration(CAMERA_APP_VIEW_TOGGLE_TIME);
58547a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeIn.setInterpolator(new DecelerateInterpolator());
58647a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang
58747a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeOut = new AlphaAnimation(1f, 0f);
58847a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeOut.setDuration(CAMERA_APP_VIEW_TOGGLE_TIME);
58947a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeOut.setInterpolator(new DecelerateInterpolator());
59047a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeOut.setAnimationListener(new HideCameraAppView());
59147a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        }
59247a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang
59378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mShowCameraAppView) {
59478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mCameraAppView.setVisibility(View.VISIBLE);
595d20805f3162b8004cc840230bc8d9c864b114401Wu-cheng Li            // The "transparent region" is not recomputed when a sibling of
596d20805f3162b8004cc840230bc8d9c864b114401Wu-cheng Li            // SurfaceView changes visibility (unless it involves GONE). It's
597d20805f3162b8004cc840230bc8d9c864b114401Wu-cheng Li            // been broken since 1.0. Call requestLayout to work around it.
598d20805f3162b8004cc840230bc8d9c864b114401Wu-cheng Li            mCameraAppView.requestLayout();
59947a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppView.startAnimation(mCameraAppViewFadeIn);
60078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        } else {
60147a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppView.startAnimation(mCameraAppViewFadeOut);
602a6b966047b6215b02c502a3f143106070abf6009Angus Kong        }
603a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
604a6b966047b6215b02c502a3f143106070abf6009Angus Kong
6058e3ccacccd2b128734322877561b8b78a70e103bWu-cheng Li    protected void onFullScreenChanged(boolean full) {
60678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mShowCameraAppView == full) return;
60778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        mShowCameraAppView = full;
60878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mPaused || isFinishing()) return;
60978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        updateCameraAppView();
610b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang
611b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        // If we received DELETE_PICTURE broadcasts while the Camera UI is
612b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        // hidden, we update the thumbnail now.
613b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        if (full && mUpdateThumbnailDelayed) {
614b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            getLastThumbnailUncached();
615b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            mUpdateThumbnailDelayed = false;
616b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        }
617a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
618a6b966047b6215b02c502a3f143106070abf6009Angus Kong
619a6b966047b6215b02c502a3f143106070abf6009Angus Kong    @Override
620a6b966047b6215b02c502a3f143106070abf6009Angus Kong    public GalleryActionBar getGalleryActionBar() {
621a6b966047b6215b02c502a3f143106070abf6009Angus Kong        return mActionBar;
622a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
6238a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li
62478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    // Preview frame layout has changed.
6258a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li    @Override
626525667ff4b93a577298085fe45660a2d15b0bd06Angus Kong    public void onLayoutChange(View v, int left, int top, int right, int bottom) {
62778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mAppBridge == null) return;
62878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
62940d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        int width = right - left;
63040d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        int height = bottom - top;
631c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li        if (ApiHelper.HAS_SURFACE_TEXTURE) {
632c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li            CameraScreenNail screenNail = (CameraScreenNail) mCameraScreenNail;
633c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li            if (Util.getDisplayRotation(this) % 180 == 0) {
634c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li                screenNail.setPreviewFrameLayoutSize(width, height);
635c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li            } else {
636c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li                // Swap the width and height. Camera screen nail draw() is based on
637c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li                // natural orientation, not the view system orientation.
638c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li                screenNail.setPreviewFrameLayoutSize(height, width);
639c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li            }
64040d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        }
64176507a9fd2581694942a662a57fbdd46d7a20036Wu-cheng Li
64278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // Find out the coordinates of the preview frame relative to GL
6438a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        // root view.
6448a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        View root = (View) getGLRoot();
6458a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        int[] rootLocation = new int[2];
6468a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        int[] viewLocation = new int[2];
6478a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        root.getLocationInWindow(rootLocation);
6488a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        v.getLocationInWindow(viewLocation);
64978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
65078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        int l = viewLocation[0] - rootLocation[0];
65178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        int t = viewLocation[1] - rootLocation[1];
65240d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        int r = l + width;
65340d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        int b = t + height;
654f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        Rect frame = new Rect(l, t, r, b);
655f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        Log.d(TAG, "set CameraRelativeFrame as " + frame);
656f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        mAppBridge.setCameraRelativeFrame(frame);
6578a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li    }
658bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
659bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    protected void setSingleTapUpListener(View singleTapArea) {
660bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        mSingleTapArea = singleTapArea;
661bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    }
662bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
66378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    private boolean onSingleTapUp(int x, int y) {
66417de506c16816a9874a5417be402345b9882e0a4Wu-cheng Li        // Ignore if listener is null or the camera control is invisible.
66517de506c16816a9874a5417be402345b9882e0a4Wu-cheng Li        if (mSingleTapArea == null || !mShowCameraAppView) return false;
666bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
667bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        int[] relativeLocation = Util.getRelativeLocation((View) getGLRoot(),
668bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li                mSingleTapArea);
669bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        x -= relativeLocation[0];
670bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        y -= relativeLocation[1];
671bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        if (x >= 0 && x < mSingleTapArea.getWidth() && y >= 0
672bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li                && y < mSingleTapArea.getHeight()) {
673bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li            onSingleTapUp(mSingleTapArea, x, y);
674bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li            return true;
675bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        }
676bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        return false;
677bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    }
678bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
679bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    protected void onSingleTapUp(View view, int x, int y) {
680bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    }
68178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
682cfbf201b06095591a2ae91af2aa4b97a9c4ae9a5George Mount    public void setSwipingEnabled(boolean enabled) {
683d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang        mAppBridge.setSwipingEnabled(enabled);
68478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    }
68578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
686e14d9149a501183d3b785f4f4aa484c4b85192d1George Mount    public void notifyScreenNailChanged() {
687a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang        mAppBridge.notifyScreenNailChanged();
688a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang    }
689a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang
690a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li    protected void onPreviewTextureCopied() {
691a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li    }
69278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
69388e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    protected void addSecureAlbumItemIfNeeded(boolean isVideo, Uri uri) {
69488e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li        if (mSecureCamera) {
69588e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li            int id = Integer.parseInt(uri.getLastPathSegment());
69688e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li            mAppBridge.addSecureAlbumItem(isVideo, id);
69788e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li        }
69888e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li    }
69988e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li
7007717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li    public boolean isSecureCamera() {
7017717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li        return mSecureCamera;
7027717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li    }
7037717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li
70478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    //////////////////////////////////////////////////////////////////////////
70578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    //  The is the communication interface between the Camera Application and
70678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    //  the Gallery PhotoPage.
70778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    //////////////////////////////////////////////////////////////////////////
70878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
709a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li    class MyAppBridge extends AppBridge implements CameraScreenNail.Listener {
710dac1bb32531f7f4d49622bd38c82dde9333c38acAhbong Chang        @SuppressWarnings("hiding")
711c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li        private ScreenNail mCameraScreenNail;
71278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        private Server mServer;
71378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
71478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
71578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public ScreenNail attachScreenNail() {
716a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang            if (mCameraScreenNail == null) {
717c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li                if (ApiHelper.HAS_SURFACE_TEXTURE) {
718c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li                    mCameraScreenNail = new CameraScreenNail(this);
719c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li                } else {
720195f07f83be795b2dfc0cdd12636a2eb4afedd86Wu-cheng Li                    Bitmap b = BitmapFactory.decodeResource(getResources(),
721195f07f83be795b2dfc0cdd12636a2eb4afedd86Wu-cheng Li                            R.drawable.wallpaper_picker_preview);
722195f07f83be795b2dfc0cdd12636a2eb4afedd86Wu-cheng Li                    mCameraScreenNail = new StaticBitmapScreenNail(b);
723c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li                }
724a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang            }
72578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            return mCameraScreenNail;
72678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
72778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
72878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
72978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public void detachScreenNail() {
73078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mCameraScreenNail = null;
73178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
73278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
733c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li        public ScreenNail getCameraScreenNail() {
73478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            return mCameraScreenNail;
73578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
73678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
73778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // Return true if the tap is consumed.
73878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
73978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public boolean onSingleTapUp(int x, int y) {
74078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            return ActivityBase.this.onSingleTapUp(x, y);
74178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
74278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
74378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // This is used to notify that the screen nail will be drawn in full screen
74478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // or not in next draw() call.
74578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
74678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public void onFullScreenChanged(boolean full) {
74778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            ActivityBase.this.onFullScreenChanged(full);
74878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
74978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
75078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
75178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public void requestRender() {
75278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            getGLRoot().requestRender();
75378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
75478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
75578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
756a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li        public void onPreviewTextureCopied() {
757a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li            ActivityBase.this.onPreviewTextureCopied();
758a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li        }
759a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li
760a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li        @Override
76178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public void setServer(Server s) {
76278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mServer = s;
76378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
76478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
76505e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong        @Override
76605e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong        public boolean isPanorama() {
76705e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong            return ActivityBase.this.isPanoramaActivity();
76805e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong        }
76905e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong
770a96d8603560c2131d1555df82b8f64c6eb06909cWu-cheng Li        @Override
771a96d8603560c2131d1555df82b8f64c6eb06909cWu-cheng Li        public boolean isStaticCamera() {
772a96d8603560c2131d1555df82b8f64c6eb06909cWu-cheng Li            return !ApiHelper.HAS_SURFACE_TEXTURE;
773a96d8603560c2131d1555df82b8f64c6eb06909cWu-cheng Li        }
774a96d8603560c2131d1555df82b8f64c6eb06909cWu-cheng Li
77588e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li        public void addSecureAlbumItem(boolean isVideo, int id) {
77688e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li            if (mServer != null) mServer.addSecureAlbumItem(isVideo, id);
77788e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li        }
77888e9e4f88caeddac4343638eb72684c70ef3d797Wu-cheng Li
779f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        private void setCameraRelativeFrame(Rect frame) {
780f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            if (mServer != null) mServer.setCameraRelativeFrame(frame);
78178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
78278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
78378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        private void switchWithCaptureAnimation(int offset) {
78478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            if (mServer != null) mServer.switchWithCaptureAnimation(offset);
78578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
786d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang
787d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang        private void setSwipingEnabled(boolean enabled) {
788d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang            if (mServer != null) mServer.setSwipingEnabled(enabled);
789d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang        }
790a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang
791a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang        private void notifyScreenNailChanged() {
792a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang            if (mServer != null) mServer.notifyScreenNailChanged();
793a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang        }
79478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    }
7954d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang}
796