ActivityBase.java revision 525667ff4b93a577298085fe45660a2d15b0bd06
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;
2478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Changimport android.graphics.Rect;
25296d27772b9543d55820e1d24d900fea959f1b7aPin Tingimport android.hardware.Camera.Parameters;
26c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.os.AsyncTask;
278608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Changimport android.os.Bundle;
28b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Changimport android.support.v4.content.LocalBroadcastManager;
297d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Millerimport android.util.Log;
304c7b291018e08dbb4bc1712d95117a294fa1416cWu-cheng Liimport android.view.KeyEvent;
3124e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Liimport android.view.Menu;
32c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.view.View;
33a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport android.view.Window;
34892781804513066b68b4a2fa6f846e862dac252aOwen Linimport android.view.WindowManager;
35525667ff4b93a577298085fe45660a2d15b0bd06Angus Kongimport android.view.animation.AlphaAnimation;
36525667ff4b93a577298085fe45660a2d15b0bd06Angus Kongimport android.view.animation.Animation;
37a029bd9976ebb618f321e8740c86b0f5d681d241Owen Linimport android.view.animation.DecelerateInterpolator;
38892781804513066b68b4a2fa6f846e862dac252aOwen Lin
39d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Liimport com.android.camera.ui.CameraPicker;
40525667ff4b93a577298085fe45660a2d15b0bd06Angus Kongimport com.android.camera.ui.LayoutChangeNotifier;
41892781804513066b68b4a2fa6f846e862dac252aOwen Linimport com.android.camera.ui.PopupManager;
42892781804513066b68b4a2fa6f846e862dac252aOwen Linimport com.android.camera.ui.RotateImageView;
43a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.app.AbstractGalleryActivity;
4478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Changimport com.android.gallery3d.app.AppBridge;
45a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.app.GalleryActionBar;
46a029bd9976ebb618f321e8740c86b0f5d681d241Owen Linimport com.android.gallery3d.app.PhotoPage;
4778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Changimport com.android.gallery3d.ui.ScreenNail;
48a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.util.MediaSetUtils;
494d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang
50aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Liimport java.io.File;
51aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
5277c1cdc8f2cda250b1db842204efb49f87e094aeChih-Chung Chang/**
537673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li * Superclass of Camera and VideoCamera activities.
5477c1cdc8f2cda250b1db842204efb49f87e094aeChih-Chung Chang */
55525667ff4b93a577298085fe45660a2d15b0bd06Angus Kongpublic abstract class ActivityBase extends AbstractGalleryActivity
56525667ff4b93a577298085fe45660a2d15b0bd06Angus Kong        implements LayoutChangeNotifier.Listener {
57a6b966047b6215b02c502a3f143106070abf6009Angus Kong
587d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    private static final String TAG = "ActivityBase";
5976507a9fd2581694942a662a57fbdd46d7a20036Wu-cheng Li    private static final boolean LOGV = false;
60c38faeb66a3f2cc96e4c5e951228d9b01e12edb3Chih-Chung Chang    private static final int CAMERA_APP_VIEW_TOGGLE_TIME = 100;  // milliseconds
61b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    private static final String ACTION_DELETE_PICTURE =
62b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            "com.android.gallery3d.action.DELETE_PICTURE";
6347a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang
645df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    private int mResultCodeForTesting;
655df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    private Intent mResultDataForTesting;
664edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    private OnScreenHint mStorageHint;
67bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    private View mSingleTapArea;
68a6b966047b6215b02c502a3f143106070abf6009Angus Kong
69c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    // The bitmap of the last captured picture thumbnail and the URI of the
70c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    // original picture.
71c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected Thumbnail mThumbnail;
728a674bebfba0c4dd4b01018276d20f198f65f19eWu-cheng Li    protected int mThumbnailViewWidth; // layout width of the thumbnail
73c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected AsyncTask<Void, Void, Thumbnail> mLoadThumbnailTask;
74d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    // An imageview showing the last captured picture thumbnail.
75d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    protected RotateImageView mThumbnailView;
76d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    protected CameraPicker mCameraPicker;
77d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li
78475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected boolean mOpenCameraFail;
79475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected boolean mCameraDisabled;
80475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected CameraManager.CameraProxy mCameraDevice;
81296d27772b9543d55820e1d24d900fea959f1b7aPin Ting    protected Parameters mParameters;
825c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li    // The activity is paused. The classes that extend this class should set
835c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li    // mPaused the first thing in onResume/onPause.
845c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li    protected boolean mPaused;
85a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected GalleryActionBar mActionBar;
86475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting
87475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    // multiple cameras support
88475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected int mNumberOfCameras;
89475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected int mCameraId;
90d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    // The activity is going to switch to the specified camera id. This is
91d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    // needed because texture copy is done in GL thread. -1 means camera is not
92d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    // switching.
93d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    protected int mPendingSwitchCameraId = -1;
94475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting
9578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    protected MyAppBridge mAppBridge;
96a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected CameraScreenNail mCameraScreenNail; // This shows camera preview.
97a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // The view containing only camera related widgets like control panel,
98a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // indicator bar, focus indicator and etc.
99a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected View mCameraAppView;
1001cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    protected boolean mShowCameraAppView = true;
10147a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang    private Animation mCameraAppViewFadeIn;
10247a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang    private Animation mCameraAppViewFadeOut;
10347a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang
104b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    private boolean mUpdateThumbnailDelayed;
105b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    private IntentFilter mDeletePictureFilter =
106b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            new IntentFilter(ACTION_DELETE_PICTURE);
107b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    private BroadcastReceiver mDeletePictureReceiver =
108b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            new BroadcastReceiver() {
109b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                @Override
110b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                public void onReceive(Context context, Intent intent) {
111b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                    if (mShowCameraAppView) {
112b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        getLastThumbnailUncached();
113b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                    } else {
114b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        mUpdateThumbnailDelayed = true;
115b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                    }
116b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                }
117b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            };
118a6b966047b6215b02c502a3f143106070abf6009Angus Kong
119475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected class CameraOpenThread extends Thread {
120475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        @Override
121475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        public void run() {
122475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            try {
123475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mCameraDevice = Util.openCamera(ActivityBase.this, mCameraId);
124296d27772b9543d55820e1d24d900fea959f1b7aPin Ting                mParameters = mCameraDevice.getParameters();
125475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            } catch (CameraHardwareException e) {
126475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mOpenCameraFail = true;
127475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            } catch (CameraDisabledException e) {
128475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mCameraDisabled = true;
129475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            }
130475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        }
131475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    }
1325df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1334d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    @Override
1348608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    public void onCreate(Bundle icicle) {
135e5b6a36e64ef2c2cb1435c138a5fc179e9a6bc9aWu-cheng Li        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
1366a4a72b643929701c5d7c8b68b91d762c7277c20Wu-cheng Li        super.disableToggleStatusBar();
137a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // Set a theme with action bar. It is not specified in manifest because
138a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // we want to hide it by default. setTheme must happen before
139a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // setContentView.
140a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        //
141a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // This must be set before we call super.onCreate(), where the window's
142a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // background is removed.
143a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        setTheme(R.style.Theme_Gallery);
144a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
145a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
146a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin
1478608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang        super.onCreate(icicle);
1488608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    }
1498608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang
15005e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong    public boolean isPanoramaActivity() {
15105e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong        return false;
15205e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong    }
15305e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong
1548608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    @Override
155b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    protected void onResume() {
156b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        super.onResume();
157b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this);
158b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        manager.registerReceiver(mDeletePictureReceiver, mDeletePictureFilter);
159b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    }
160b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang
161b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    @Override
1627d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    protected void onPause() {
1635c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li        super.onPause();
164b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this);
165b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        manager.unregisterReceiver(mDeletePictureReceiver);
166b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang
1677d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        if (LOGV) Log.v(TAG, "onPause");
168aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        saveThumbnailToFile();
1694edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong
170c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mLoadThumbnailTask != null) {
171c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask.cancel(true);
172c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask = null;
173c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
174c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
1754edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (mStorageHint != null) {
1764edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.cancel();
1774edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint = null;
1784edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
1797d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    }
1807d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
1817d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    @Override
18272fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li    public void setContentView(int layoutResID) {
18372fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        super.setContentView(layoutResID);
18472fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        // getActionBar() should be after setContentView
18572fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        mActionBar = new GalleryActionBar(this);
18672fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        mActionBar.hide();
18772fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li    }
18872fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li
18972fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li    @Override
1904d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    public boolean onSearchRequested() {
1914d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang        return false;
1924d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    }
1937673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li
1947673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    @Override
1957673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    public boolean onKeyDown(int keyCode, KeyEvent event) {
1967673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        // Prevent software keyboard or voice search from showing up.
1977673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        if (keyCode == KeyEvent.KEYCODE_SEARCH
1987673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li                || keyCode == KeyEvent.KEYCODE_MENU) {
1997673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li            if (event.isLongPress()) return true;
2007673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        }
2017673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li
2027673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        return super.onKeyDown(keyCode, event);
2037673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    }
2045df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
2055df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    protected void setResultEx(int resultCode) {
2065df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultCodeForTesting = resultCode;
2075df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        setResult(resultCode);
2085df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
2095df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
2105df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    protected void setResultEx(int resultCode, Intent data) {
2115df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultCodeForTesting = resultCode;
2125df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultDataForTesting = data;
2135df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        setResult(resultCode, data);
2145df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
2155df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
2165df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    public int getResultCode() {
2175df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        return mResultCodeForTesting;
2185df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
2195df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
2205df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    public Intent getResultData() {
2215df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        return mResultDataForTesting;
2225df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
2235f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang
2245f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    @Override
2255f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    protected void onDestroy() {
2265f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang        PopupManager.removeInstance(this);
2275f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang        super.onDestroy();
2285f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    }
2297d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
23024e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li    @Override
23124e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li    public boolean onCreateOptionsMenu(Menu menu) {
23224e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li        super.onCreateOptionsMenu(menu);
23324e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li        return getStateManager().createOptionsMenu(menu);
23424e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li    }
23524e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li
2364edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    protected void updateStorageHint(long storageSpace) {
2374edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        String message = null;
2384edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (storageSpace == Storage.UNAVAILABLE) {
2394edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.no_storage);
2404edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace == Storage.PREPARING) {
2414edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.preparing_sd);
2424edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace == Storage.UNKNOWN_SIZE) {
2434edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.access_sd_fail);
2444edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace < Storage.LOW_STORAGE_THRESHOLD) {
2454edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.spaceIsLow_content);
2464edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
2474edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong
2484edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (message != null) {
2494edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            if (mStorageHint == null) {
2504edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong                mStorageHint = OnScreenHint.makeText(this, message);
2514edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            } else {
2524edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong                mStorageHint.setText(message);
2534edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            }
2544edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.show();
2554edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (mStorageHint != null) {
2564edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.cancel();
2574edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint = null;
2584edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
2594edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    }
260c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
261a0b7c6b3c61b68db7f4eb33d81c886fb4e095f2cPin Ting    protected void updateThumbnailView() {
262c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mThumbnail != null) {
263c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setBitmap(mThumbnail.getBitmap());
264c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setVisibility(View.VISIBLE);
265c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        } else {
266c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setBitmap(null);
267c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setVisibility(View.GONE);
268c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
269c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
270c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
271c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected void getLastThumbnail() {
272c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        mThumbnail = ThumbnailHolder.getLastThumbnail(getContentResolver());
273c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // Suppose users tap the thumbnail view, go to the gallery, delete the
274c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // image, and coming back to the camera. Thumbnail file will be invalid.
275c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // Since the new thumbnail will be loaded in another thread later, the
276c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // view should be set to gone to prevent from opening the invalid image.
277c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        updateThumbnailView();
278c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mThumbnail == null) {
279b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            mLoadThumbnailTask = new LoadThumbnailTask(true).execute();
280c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
281c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
282c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
283b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    protected void getLastThumbnailUncached() {
284b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        if (mLoadThumbnailTask != null) mLoadThumbnailTask.cancel(true);
285b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        mLoadThumbnailTask = new LoadThumbnailTask(false).execute();
286b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang    }
287b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang
288aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    private class LoadThumbnailTask extends AsyncTask<Void, Void, Thumbnail> {
289b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        private boolean mLookAtCache;
290b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang
291b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        public LoadThumbnailTask(boolean lookAtCache) {
292b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            mLookAtCache = lookAtCache;
293b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        }
294b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang
295c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        @Override
296c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        protected Thumbnail doInBackground(Void... params) {
297c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            // Load the thumbnail from the file.
298c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            ContentResolver resolver = getContentResolver();
299b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            Thumbnail t = null;
300b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            if (mLookAtCache) {
301b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                t = Thumbnail.getLastThumbnailFromFile(getFilesDir(), resolver);
302b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            }
303c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
304c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            if (isCancelled()) return null;
305c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
306c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            if (t == null) {
307b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                Thumbnail result[] = new Thumbnail[1];
308c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li                // Load the thumbnail from the media provider.
309b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                int code = Thumbnail.getLastThumbnailFromContentResolver(
310b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        resolver, result);
311b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                switch (code) {
312b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                    case Thumbnail.THUMBNAIL_FOUND:
313b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        return result[0];
314b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                    case Thumbnail.THUMBNAIL_NOT_FOUND:
315b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        return null;
316b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                    case Thumbnail.THUMBNAIL_DELETED:
317b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        cancel(true);
318b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                        return null;
319b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang                }
320c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            }
321c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            return t;
322c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
323c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
324c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        @Override
325c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        protected void onPostExecute(Thumbnail thumbnail) {
326b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            if (isCancelled()) return;
327c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnail = thumbnail;
328c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            updateThumbnailView();
329c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
330c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
331aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
3326899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting    protected void gotoGallery() {
333252da3c55a35c77fa4be4d51f79dac4aaf7cdb77Pin Ting        // Move the next picture with capture animation. "1" means next.
334252da3c55a35c77fa4be4d51f79dac4aaf7cdb77Pin Ting        mAppBridge.switchWithCaptureAnimation(1);
3356899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting    }
3366899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting
337aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    protected void saveThumbnailToFile() {
338aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        if (mThumbnail != null && !mThumbnail.fromFile()) {
339aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            new SaveThumbnailTask().execute(mThumbnail);
340aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        }
341aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    }
342aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
343aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    private class SaveThumbnailTask extends AsyncTask<Thumbnail, Void, Void> {
344aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        @Override
345aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        protected Void doInBackground(Thumbnail... params) {
346aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            final int n = params.length;
347aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            final File filesDir = getFilesDir();
348aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            for (int i = 0; i < n; i++) {
349aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li                params[i].saveLastThumbnailToFile(filesDir);
350aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            }
351aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            return null;
352aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        }
353aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    }
354a6b966047b6215b02c502a3f143106070abf6009Angus Kong
355a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // Call this after setContentView.
356a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected void createCameraScreenNail(boolean getPictures) {
357a6b966047b6215b02c502a3f143106070abf6009Angus Kong        mCameraAppView = findViewById(R.id.camera_app_root);
358a6b966047b6215b02c502a3f143106070abf6009Angus Kong        Bundle data = new Bundle();
359a6b966047b6215b02c502a3f143106070abf6009Angus Kong        String path = "/local/all/";
360a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // Intent mode does not show camera roll. Use 0 as a work around for
361a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // invalid bucket id.
362a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // TODO: add support of empty media set in gallery.
363a6b966047b6215b02c502a3f143106070abf6009Angus Kong        path += (getPictures ? MediaSetUtils.CAMERA_BUCKET_ID : "0");
364a6b966047b6215b02c502a3f143106070abf6009Angus Kong        data.putString(PhotoPage.KEY_MEDIA_SET_PATH, path);
365a6b966047b6215b02c502a3f143106070abf6009Angus Kong        data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, path);
366a6b966047b6215b02c502a3f143106070abf6009Angus Kong
36778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // Send an AppBridge to gallery to enable the camera preview.
36878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        mAppBridge = new MyAppBridge();
36978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        data.putParcelable(PhotoPage.KEY_APP_BRIDGE, mAppBridge);
370a6b966047b6215b02c502a3f143106070abf6009Angus Kong        getStateManager().startState(PhotoPage.class, data);
37178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        mCameraScreenNail = mAppBridge.getCameraScreenNail();
372a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
373a6b966047b6215b02c502a3f143106070abf6009Angus Kong
37447a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang    private class HideCameraAppView implements Animation.AnimationListener {
3751cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        @Override
37647a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        public void onAnimationEnd(Animation animation) {
377f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            // We cannot set this as GONE because we want to receive the
378f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            // onLayoutChange() callback even when we are invisible.
379f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            mCameraAppView.setVisibility(View.INVISIBLE);
3801cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        }
38147a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang
38247a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        @Override
38347a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        public void onAnimationRepeat(Animation animation) {
38447a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        }
38547a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang
38647a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        @Override
38747a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        public void onAnimationStart(Animation animation) {
38847a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        }
3891cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    }
39078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
391c94cd4a5206b05541de0dc8a4821c64d0edba352Angus Kong    protected void updateCameraAppView() {
39247a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        // Initialize the animation.
39347a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        if (mCameraAppViewFadeIn == null) {
39447a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeIn = new AlphaAnimation(0f, 1f);
39547a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeIn.setDuration(CAMERA_APP_VIEW_TOGGLE_TIME);
39647a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeIn.setInterpolator(new DecelerateInterpolator());
39747a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang
39847a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeOut = new AlphaAnimation(1f, 0f);
39947a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeOut.setDuration(CAMERA_APP_VIEW_TOGGLE_TIME);
40047a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeOut.setInterpolator(new DecelerateInterpolator());
40147a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppViewFadeOut.setAnimationListener(new HideCameraAppView());
40247a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang        }
40347a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang
40478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mShowCameraAppView) {
40578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mCameraAppView.setVisibility(View.VISIBLE);
406d20805f3162b8004cc840230bc8d9c864b114401Wu-cheng Li            // The "transparent region" is not recomputed when a sibling of
407d20805f3162b8004cc840230bc8d9c864b114401Wu-cheng Li            // SurfaceView changes visibility (unless it involves GONE). It's
408d20805f3162b8004cc840230bc8d9c864b114401Wu-cheng Li            // been broken since 1.0. Call requestLayout to work around it.
409d20805f3162b8004cc840230bc8d9c864b114401Wu-cheng Li            mCameraAppView.requestLayout();
41047a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppView.startAnimation(mCameraAppViewFadeIn);
41178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        } else {
41247a563b623a468f736779da7e21ef69665fc5b80Chih-Yu Huang            mCameraAppView.startAnimation(mCameraAppViewFadeOut);
413a6b966047b6215b02c502a3f143106070abf6009Angus Kong        }
414a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
415a6b966047b6215b02c502a3f143106070abf6009Angus Kong
41678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    private void onFullScreenChanged(boolean full) {
41778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mShowCameraAppView == full) return;
41878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        mShowCameraAppView = full;
41978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mPaused || isFinishing()) return;
42078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        updateCameraAppView();
421b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang
422b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        // If we received DELETE_PICTURE broadcasts while the Camera UI is
423b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        // hidden, we update the thumbnail now.
424b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        if (full && mUpdateThumbnailDelayed) {
425b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            getLastThumbnailUncached();
426b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang            mUpdateThumbnailDelayed = false;
427b2838c064ed33d8abd2e6dc7ea38659a3bb686f9Chih-Chung Chang        }
428a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
429a6b966047b6215b02c502a3f143106070abf6009Angus Kong
430a6b966047b6215b02c502a3f143106070abf6009Angus Kong    @Override
431a6b966047b6215b02c502a3f143106070abf6009Angus Kong    public GalleryActionBar getGalleryActionBar() {
432a6b966047b6215b02c502a3f143106070abf6009Angus Kong        return mActionBar;
433a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
4348a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li
43578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    // Preview frame layout has changed.
4368a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li    @Override
437525667ff4b93a577298085fe45660a2d15b0bd06Angus Kong    public void onLayoutChange(View v, int left, int top, int right, int bottom) {
43878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mAppBridge == null) return;
43978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
44040d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        int width = right - left;
44140d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        int height = bottom - top;
44240d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        if (Util.getDisplayRotation(this) % 180 == 0) {
44340d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li            mCameraScreenNail.setPreviewFrameLayoutSize(width, height);
44440d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        } else {
44540d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li            // Swap the width and height. Camera screen nail draw() is based on
44640d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li            // natural orientation, not the view system orientation.
44740d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li            mCameraScreenNail.setPreviewFrameLayoutSize(height, width);
44840d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        }
44976507a9fd2581694942a662a57fbdd46d7a20036Wu-cheng Li
45078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // Find out the coordinates of the preview frame relative to GL
4518a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        // root view.
4528a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        View root = (View) getGLRoot();
4538a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        int[] rootLocation = new int[2];
4548a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        int[] viewLocation = new int[2];
4558a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        root.getLocationInWindow(rootLocation);
4568a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        v.getLocationInWindow(viewLocation);
45778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
45878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        int l = viewLocation[0] - rootLocation[0];
45978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        int t = viewLocation[1] - rootLocation[1];
46040d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        int r = l + width;
46140d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        int b = t + height;
462f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        Rect frame = new Rect(l, t, r, b);
463f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        Log.d(TAG, "set CameraRelativeFrame as " + frame);
464f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        mAppBridge.setCameraRelativeFrame(frame);
4658a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li    }
466bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
467bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    protected void setSingleTapUpListener(View singleTapArea) {
468bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        mSingleTapArea = singleTapArea;
469bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    }
470bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
47178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    private boolean onSingleTapUp(int x, int y) {
47217de506c16816a9874a5417be402345b9882e0a4Wu-cheng Li        // Ignore if listener is null or the camera control is invisible.
47317de506c16816a9874a5417be402345b9882e0a4Wu-cheng Li        if (mSingleTapArea == null || !mShowCameraAppView) return false;
474bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
475bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        int[] relativeLocation = Util.getRelativeLocation((View) getGLRoot(),
476bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li                mSingleTapArea);
477bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        x -= relativeLocation[0];
478bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        y -= relativeLocation[1];
479bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        if (x >= 0 && x < mSingleTapArea.getWidth() && y >= 0
480bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li                && y < mSingleTapArea.getHeight()) {
481bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li            onSingleTapUp(mSingleTapArea, x, y);
482bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li            return true;
483bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        }
484bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        return false;
485bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    }
486bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
487bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    protected void onSingleTapUp(View view, int x, int y) {
488bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    }
48978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
490d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang    protected void setSwipingEnabled(boolean enabled) {
491d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang        mAppBridge.setSwipingEnabled(enabled);
49278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    }
49378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
494a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang    protected void notifyScreenNailChanged() {
495a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang        mAppBridge.notifyScreenNailChanged();
496a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang    }
497a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang
498a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li    protected void onPreviewTextureCopied() {
499a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li    }
50078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
50178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    //////////////////////////////////////////////////////////////////////////
50278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    //  The is the communication interface between the Camera Application and
50378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    //  the Gallery PhotoPage.
50478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    //////////////////////////////////////////////////////////////////////////
50578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
506a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li    class MyAppBridge extends AppBridge implements CameraScreenNail.Listener {
50778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        private CameraScreenNail mCameraScreenNail;
50878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        private Server mServer;
50978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
51078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
51178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public ScreenNail attachScreenNail() {
512a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang            if (mCameraScreenNail == null) {
513a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang                mCameraScreenNail = new CameraScreenNail(this);
514a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang            }
51578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            return mCameraScreenNail;
51678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
51778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
51878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
51978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public void detachScreenNail() {
52078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mCameraScreenNail = null;
52178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
52278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
52378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public CameraScreenNail getCameraScreenNail() {
52478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            return mCameraScreenNail;
52578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
52678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
52778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // Return true if the tap is consumed.
52878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
52978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public boolean onSingleTapUp(int x, int y) {
53078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            return ActivityBase.this.onSingleTapUp(x, y);
53178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
53278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
53378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // This is used to notify that the screen nail will be drawn in full screen
53478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // or not in next draw() call.
53578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
53678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public void onFullScreenChanged(boolean full) {
53778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            ActivityBase.this.onFullScreenChanged(full);
53878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
53978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
54078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
54178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public void requestRender() {
54278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            getGLRoot().requestRender();
54378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
54478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
54578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
546a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li        public void onPreviewTextureCopied() {
547a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li            ActivityBase.this.onPreviewTextureCopied();
548a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li        }
549a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li
550a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li        @Override
55178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public void setServer(Server s) {
55278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mServer = s;
55378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
55478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
55505e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong        @Override
55605e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong        public boolean isPanorama() {
55705e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong            return ActivityBase.this.isPanoramaActivity();
55805e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong        }
55905e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong
560f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        private void setCameraRelativeFrame(Rect frame) {
561f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            if (mServer != null) mServer.setCameraRelativeFrame(frame);
56278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
56378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
56478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        private void switchWithCaptureAnimation(int offset) {
56578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            if (mServer != null) mServer.switchWithCaptureAnimation(offset);
56678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
567d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang
568d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang        private void setSwipingEnabled(boolean enabled) {
569d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang            if (mServer != null) mServer.setSwipingEnabled(enabled);
570d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang        }
571a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang
572a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang        private void notifyScreenNailChanged() {
573a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang            if (mServer != null) mServer.notifyScreenNailChanged();
574a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang        }
57578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    }
5764d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang}
577