ActivityBase.java revision c94cd4a5206b05541de0dc8a4821c64d0edba352
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
19c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.content.ContentResolver;
205df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Liimport android.content.Intent;
2178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Changimport android.graphics.Rect;
22296d27772b9543d55820e1d24d900fea959f1b7aPin Tingimport android.hardware.Camera.Parameters;
23c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.os.AsyncTask;
248608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Changimport android.os.Bundle;
257d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Millerimport android.util.Log;
264c7b291018e08dbb4bc1712d95117a294fa1416cWu-cheng Liimport android.view.KeyEvent;
2724e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Liimport android.view.Menu;
28c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.view.View;
29a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport android.view.Window;
30892781804513066b68b4a2fa6f846e862dac252aOwen Linimport android.view.WindowManager;
31a029bd9976ebb618f321e8740c86b0f5d681d241Owen Linimport android.view.animation.DecelerateInterpolator;
32892781804513066b68b4a2fa6f846e862dac252aOwen Lin
33d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Liimport com.android.camera.ui.CameraPicker;
34892781804513066b68b4a2fa6f846e862dac252aOwen Linimport com.android.camera.ui.PopupManager;
35892781804513066b68b4a2fa6f846e862dac252aOwen Linimport com.android.camera.ui.RotateImageView;
36a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.app.AbstractGalleryActivity;
3778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Changimport com.android.gallery3d.app.AppBridge;
38a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.app.GalleryActionBar;
39a029bd9976ebb618f321e8740c86b0f5d681d241Owen Linimport com.android.gallery3d.app.PhotoPage;
4078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Changimport com.android.gallery3d.ui.ScreenNail;
41a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.util.MediaSetUtils;
424d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang
43aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Liimport java.io.File;
44aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
4577c1cdc8f2cda250b1db842204efb49f87e094aeChih-Chung Chang/**
467673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li * Superclass of Camera and VideoCamera activities.
4777c1cdc8f2cda250b1db842204efb49f87e094aeChih-Chung Chang */
48a6b966047b6215b02c502a3f143106070abf6009Angus Kongabstract public class ActivityBase extends AbstractGalleryActivity
4978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        implements View.OnLayoutChangeListener {
50a6b966047b6215b02c502a3f143106070abf6009Angus Kong
517d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    private static final String TAG = "ActivityBase";
5276507a9fd2581694942a662a57fbdd46d7a20036Wu-cheng Li    private static final boolean LOGV = false;
53c38faeb66a3f2cc96e4c5e951228d9b01e12edb3Chih-Chung Chang    private static final int CAMERA_APP_VIEW_TOGGLE_TIME = 100;  // milliseconds
545df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    private int mResultCodeForTesting;
555df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    private Intent mResultDataForTesting;
564edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    private OnScreenHint mStorageHint;
571cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    private HideCameraAppView mHideCameraAppView;
58bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    private View mSingleTapArea;
59a6b966047b6215b02c502a3f143106070abf6009Angus Kong
60c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    // The bitmap of the last captured picture thumbnail and the URI of the
61c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    // original picture.
62c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected Thumbnail mThumbnail;
638a674bebfba0c4dd4b01018276d20f198f65f19eWu-cheng Li    protected int mThumbnailViewWidth; // layout width of the thumbnail
64c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected AsyncTask<Void, Void, Thumbnail> mLoadThumbnailTask;
65d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    // An imageview showing the last captured picture thumbnail.
66d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    protected RotateImageView mThumbnailView;
67d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    protected CameraPicker mCameraPicker;
68d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li
69475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected boolean mOpenCameraFail;
70475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected boolean mCameraDisabled;
71475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected CameraManager.CameraProxy mCameraDevice;
72296d27772b9543d55820e1d24d900fea959f1b7aPin Ting    protected Parameters mParameters;
735c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li    // The activity is paused. The classes that extend this class should set
745c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li    // mPaused the first thing in onResume/onPause.
755c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li    protected boolean mPaused;
76a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected GalleryActionBar mActionBar;
77475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting
78475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    // multiple cameras support
79475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected int mNumberOfCameras;
80475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected int mCameraId;
81d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    // The activity is going to switch to the specified camera id. This is
82d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    // needed because texture copy is done in GL thread. -1 means camera is not
83d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    // switching.
84d97ddcbe7e765b45e68e157af7ac0c873a165aa9Wu-cheng Li    protected int mPendingSwitchCameraId = -1;
85475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting
8678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    protected MyAppBridge mAppBridge;
87a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected CameraScreenNail mCameraScreenNail; // This shows camera preview.
88a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // The view containing only camera related widgets like control panel,
89a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // indicator bar, focus indicator and etc.
90a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected View mCameraAppView;
911cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    protected boolean mShowCameraAppView = true;
92a6b966047b6215b02c502a3f143106070abf6009Angus Kong
93475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected class CameraOpenThread extends Thread {
94475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        @Override
95475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        public void run() {
96475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            try {
97475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mCameraDevice = Util.openCamera(ActivityBase.this, mCameraId);
98296d27772b9543d55820e1d24d900fea959f1b7aPin Ting                mParameters = mCameraDevice.getParameters();
99475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            } catch (CameraHardwareException e) {
100475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mOpenCameraFail = true;
101475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            } catch (CameraDisabledException e) {
102475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mCameraDisabled = true;
103475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            }
104475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        }
105475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    }
1065df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1074d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    @Override
1088608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    public void onCreate(Bundle icicle) {
109e5b6a36e64ef2c2cb1435c138a5fc179e9a6bc9aWu-cheng Li        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
1106a4a72b643929701c5d7c8b68b91d762c7277c20Wu-cheng Li        super.disableToggleStatusBar();
111a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // Set a theme with action bar. It is not specified in manifest because
112a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // we want to hide it by default. setTheme must happen before
113a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // setContentView.
114a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        //
115a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // This must be set before we call super.onCreate(), where the window's
116a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        // background is removed.
117a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        setTheme(R.style.Theme_Gallery);
118a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
119a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin        requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
120a029bd9976ebb618f321e8740c86b0f5d681d241Owen Lin
1218608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang        super.onCreate(icicle);
1228608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    }
1238608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang
12405e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong    public boolean isPanoramaActivity() {
12505e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong        return false;
12605e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong    }
12705e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong
1288608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    @Override
1297d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    protected void onPause() {
1305c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li        super.onPause();
1317d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        if (LOGV) Log.v(TAG, "onPause");
132aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        saveThumbnailToFile();
1334edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong
134c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mLoadThumbnailTask != null) {
135c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask.cancel(true);
136c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask = null;
137c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
138c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
1394edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (mStorageHint != null) {
1404edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.cancel();
1414edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint = null;
1424edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
1437d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    }
1447d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
1457d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    @Override
14672fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li    public void setContentView(int layoutResID) {
14772fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        super.setContentView(layoutResID);
14872fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        // getActionBar() should be after setContentView
14972fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        mActionBar = new GalleryActionBar(this);
15072fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        mActionBar.hide();
15172fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li    }
15272fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li
15372fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li    @Override
1544d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    public boolean onSearchRequested() {
1554d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang        return false;
1564d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    }
1577673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li
1587673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    @Override
1597673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    public boolean onKeyDown(int keyCode, KeyEvent event) {
1607673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        // Prevent software keyboard or voice search from showing up.
1617673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        if (keyCode == KeyEvent.KEYCODE_SEARCH
1627673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li                || keyCode == KeyEvent.KEYCODE_MENU) {
1637673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li            if (event.isLongPress()) return true;
1647673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        }
1657673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li
1667673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        return super.onKeyDown(keyCode, event);
1677673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    }
1685df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1695df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    protected void setResultEx(int resultCode) {
1705df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultCodeForTesting = resultCode;
1715df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        setResult(resultCode);
1725df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
1735df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1745df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    protected void setResultEx(int resultCode, Intent data) {
1755df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultCodeForTesting = resultCode;
1765df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultDataForTesting = data;
1775df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        setResult(resultCode, data);
1785df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
1795df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1805df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    public int getResultCode() {
1815df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        return mResultCodeForTesting;
1825df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
1835df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1845df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    public Intent getResultData() {
1855df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        return mResultDataForTesting;
1865df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
1875f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang
1885f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    @Override
1895f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    protected void onDestroy() {
1905f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang        PopupManager.removeInstance(this);
1915f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang        super.onDestroy();
1925f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    }
1937d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
19424e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li    @Override
19524e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li    public boolean onCreateOptionsMenu(Menu menu) {
19624e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li        super.onCreateOptionsMenu(menu);
19724e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li        return getStateManager().createOptionsMenu(menu);
19824e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li    }
19924e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li
2004edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    protected void updateStorageHint(long storageSpace) {
2014edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        String message = null;
2024edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (storageSpace == Storage.UNAVAILABLE) {
2034edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.no_storage);
2044edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace == Storage.PREPARING) {
2054edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.preparing_sd);
2064edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace == Storage.UNKNOWN_SIZE) {
2074edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.access_sd_fail);
2084edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace < Storage.LOW_STORAGE_THRESHOLD) {
2094edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.spaceIsLow_content);
2104edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
2114edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong
2124edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (message != null) {
2134edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            if (mStorageHint == null) {
2144edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong                mStorageHint = OnScreenHint.makeText(this, message);
2154edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            } else {
2164edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong                mStorageHint.setText(message);
2174edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            }
2184edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.show();
2194edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (mStorageHint != null) {
2204edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.cancel();
2214edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint = null;
2224edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
2234edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    }
224c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
225a0b7c6b3c61b68db7f4eb33d81c886fb4e095f2cPin Ting    protected void updateThumbnailView() {
226c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mThumbnail != null) {
227c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setBitmap(mThumbnail.getBitmap());
228c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setVisibility(View.VISIBLE);
229c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        } else {
230c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setBitmap(null);
231c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setVisibility(View.GONE);
232c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
233c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
234c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
235c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected void getLastThumbnail() {
236c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        mThumbnail = ThumbnailHolder.getLastThumbnail(getContentResolver());
237c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // Suppose users tap the thumbnail view, go to the gallery, delete the
238c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // image, and coming back to the camera. Thumbnail file will be invalid.
239c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // Since the new thumbnail will be loaded in another thread later, the
240c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // view should be set to gone to prevent from opening the invalid image.
241c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        updateThumbnailView();
242c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mThumbnail == null) {
243c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask = new LoadThumbnailTask().execute();
244c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
245c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
246c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
247aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    private class LoadThumbnailTask extends AsyncTask<Void, Void, Thumbnail> {
248c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        @Override
249c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        protected Thumbnail doInBackground(Void... params) {
250c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            // Load the thumbnail from the file.
251c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            ContentResolver resolver = getContentResolver();
252c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            Thumbnail t = Thumbnail.getLastThumbnailFromFile(getFilesDir(), resolver);
253c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
254c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            if (isCancelled()) return null;
255c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
256c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            if (t == null) {
257c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li                // Load the thumbnail from the media provider.
258c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li                t = Thumbnail.getLastThumbnailFromContentResolver(resolver);
259c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            }
260c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            return t;
261c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
262c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
263c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        @Override
264c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        protected void onPostExecute(Thumbnail thumbnail) {
265c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnail = thumbnail;
266c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            updateThumbnailView();
267c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
268c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
269aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
2706899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting    protected void gotoGallery() {
271252da3c55a35c77fa4be4d51f79dac4aaf7cdb77Pin Ting        // Move the next picture with capture animation. "1" means next.
272252da3c55a35c77fa4be4d51f79dac4aaf7cdb77Pin Ting        mAppBridge.switchWithCaptureAnimation(1);
2736899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting    }
2746899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting
275aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    protected void saveThumbnailToFile() {
276aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        if (mThumbnail != null && !mThumbnail.fromFile()) {
277aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            new SaveThumbnailTask().execute(mThumbnail);
278aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        }
279aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    }
280aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
281aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    private class SaveThumbnailTask extends AsyncTask<Thumbnail, Void, Void> {
282aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        @Override
283aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        protected Void doInBackground(Thumbnail... params) {
284aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            final int n = params.length;
285aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            final File filesDir = getFilesDir();
286aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            for (int i = 0; i < n; i++) {
287aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li                params[i].saveLastThumbnailToFile(filesDir);
288aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            }
289aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            return null;
290aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        }
291aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    }
292a6b966047b6215b02c502a3f143106070abf6009Angus Kong
293a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // Call this after setContentView.
294a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected void createCameraScreenNail(boolean getPictures) {
295a6b966047b6215b02c502a3f143106070abf6009Angus Kong        mCameraAppView = findViewById(R.id.camera_app_root);
296a6b966047b6215b02c502a3f143106070abf6009Angus Kong        Bundle data = new Bundle();
297a6b966047b6215b02c502a3f143106070abf6009Angus Kong        String path = "/local/all/";
298a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // Intent mode does not show camera roll. Use 0 as a work around for
299a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // invalid bucket id.
300a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // TODO: add support of empty media set in gallery.
301a6b966047b6215b02c502a3f143106070abf6009Angus Kong        path += (getPictures ? MediaSetUtils.CAMERA_BUCKET_ID : "0");
302a6b966047b6215b02c502a3f143106070abf6009Angus Kong        data.putString(PhotoPage.KEY_MEDIA_SET_PATH, path);
303a6b966047b6215b02c502a3f143106070abf6009Angus Kong        data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, path);
304a6b966047b6215b02c502a3f143106070abf6009Angus Kong
30578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // Send an AppBridge to gallery to enable the camera preview.
30678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        mAppBridge = new MyAppBridge();
30778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        data.putParcelable(PhotoPage.KEY_APP_BRIDGE, mAppBridge);
308a6b966047b6215b02c502a3f143106070abf6009Angus Kong        getStateManager().startState(PhotoPage.class, data);
30978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        mCameraScreenNail = mAppBridge.getCameraScreenNail();
310a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
311a6b966047b6215b02c502a3f143106070abf6009Angus Kong
3121cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    private class HideCameraAppView implements Runnable {
3131cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        @Override
3141cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        public void run() {
315f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            // We cannot set this as GONE because we want to receive the
316f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            // onLayoutChange() callback even when we are invisible.
317f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            mCameraAppView.setVisibility(View.INVISIBLE);
3181cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        }
3191cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    }
32078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
321c94cd4a5206b05541de0dc8a4821c64d0edba352Angus Kong    protected void updateCameraAppView() {
32278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mShowCameraAppView) {
32378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mCameraAppView.setVisibility(View.VISIBLE);
324d20805f3162b8004cc840230bc8d9c864b114401Wu-cheng Li            // The "transparent region" is not recomputed when a sibling of
325d20805f3162b8004cc840230bc8d9c864b114401Wu-cheng Li            // SurfaceView changes visibility (unless it involves GONE). It's
326d20805f3162b8004cc840230bc8d9c864b114401Wu-cheng Li            // been broken since 1.0. Call requestLayout to work around it.
327d20805f3162b8004cc840230bc8d9c864b114401Wu-cheng Li            mCameraAppView.requestLayout();
328f108795408821e4b930c28a68f8a35972e621f4ePin Ting            // withEndAction(null) prevents the pending end action
329f108795408821e4b930c28a68f8a35972e621f4ePin Ting            // mHideCameraAppView from being executed.
33078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mCameraAppView.animate()
331f108795408821e4b930c28a68f8a35972e621f4ePin Ting                    .setDuration(CAMERA_APP_VIEW_TOGGLE_TIME)
332f108795408821e4b930c28a68f8a35972e621f4ePin Ting                    .withLayer().alpha(1).withEndAction(null);
33378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        } else {
33478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mCameraAppView.animate()
335f108795408821e4b930c28a68f8a35972e621f4ePin Ting                    .setDuration(CAMERA_APP_VIEW_TOGGLE_TIME)
336f108795408821e4b930c28a68f8a35972e621f4ePin Ting                    .withLayer().alpha(0).withEndAction(mHideCameraAppView);
337a6b966047b6215b02c502a3f143106070abf6009Angus Kong        }
338a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
339a6b966047b6215b02c502a3f143106070abf6009Angus Kong
34078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    private void onFullScreenChanged(boolean full) {
34178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mShowCameraAppView == full) return;
34278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        mShowCameraAppView = full;
34378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mPaused || isFinishing()) return;
34478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // Initialize the animation.
34578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mHideCameraAppView == null) {
34678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mHideCameraAppView = new HideCameraAppView();
34778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mCameraAppView.animate()
34878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang                .setInterpolator(new DecelerateInterpolator());
349a6b966047b6215b02c502a3f143106070abf6009Angus Kong        }
35078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        updateCameraAppView();
351a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
352a6b966047b6215b02c502a3f143106070abf6009Angus Kong
353a6b966047b6215b02c502a3f143106070abf6009Angus Kong    @Override
354a6b966047b6215b02c502a3f143106070abf6009Angus Kong    public GalleryActionBar getGalleryActionBar() {
355a6b966047b6215b02c502a3f143106070abf6009Angus Kong        return mActionBar;
356a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
3578a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li
35878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    // Preview frame layout has changed.
3598a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li    @Override
3608a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li    public void onLayoutChange(View v, int left, int top, int right, int bottom,
3618a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li            int oldLeft, int oldTop, int oldRight, int oldBottom) {
36278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        if (mAppBridge == null) return;
36378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
364f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        if (left == oldLeft && top == oldTop && right == oldRight
365f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang                && bottom == oldBottom) {
366f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            return;
367f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        }
368f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang
36940d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li
37040d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        int width = right - left;
37140d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        int height = bottom - top;
37240d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        if (Util.getDisplayRotation(this) % 180 == 0) {
37340d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li            mCameraScreenNail.setPreviewFrameLayoutSize(width, height);
37440d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        } else {
37540d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li            // Swap the width and height. Camera screen nail draw() is based on
37640d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li            // natural orientation, not the view system orientation.
37740d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li            mCameraScreenNail.setPreviewFrameLayoutSize(height, width);
37840d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        }
37976507a9fd2581694942a662a57fbdd46d7a20036Wu-cheng Li
38078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // Find out the coordinates of the preview frame relative to GL
3818a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        // root view.
3828a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        View root = (View) getGLRoot();
3838a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        int[] rootLocation = new int[2];
3848a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        int[] viewLocation = new int[2];
3858a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        root.getLocationInWindow(rootLocation);
3868a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        v.getLocationInWindow(viewLocation);
38778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
38878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        int l = viewLocation[0] - rootLocation[0];
38978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        int t = viewLocation[1] - rootLocation[1];
39040d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        int r = l + width;
39140d99c1258ef297c18bf0857860b326d517bf4aaWu-cheng Li        int b = t + height;
392f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        Rect frame = new Rect(l, t, r, b);
393f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        Log.d(TAG, "set CameraRelativeFrame as " + frame);
394f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        mAppBridge.setCameraRelativeFrame(frame);
3958a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li    }
396bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
397bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    protected void setSingleTapUpListener(View singleTapArea) {
398bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        mSingleTapArea = singleTapArea;
399bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    }
400bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
40178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    private boolean onSingleTapUp(int x, int y) {
40217de506c16816a9874a5417be402345b9882e0a4Wu-cheng Li        // Ignore if listener is null or the camera control is invisible.
40317de506c16816a9874a5417be402345b9882e0a4Wu-cheng Li        if (mSingleTapArea == null || !mShowCameraAppView) return false;
404bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
405bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        int[] relativeLocation = Util.getRelativeLocation((View) getGLRoot(),
406bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li                mSingleTapArea);
407bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        x -= relativeLocation[0];
408bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        y -= relativeLocation[1];
409bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        if (x >= 0 && x < mSingleTapArea.getWidth() && y >= 0
410bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li                && y < mSingleTapArea.getHeight()) {
411bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li            onSingleTapUp(mSingleTapArea, x, y);
412bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li            return true;
413bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        }
414bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        return false;
415bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    }
416bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
417bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    protected void onSingleTapUp(View view, int x, int y) {
418bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    }
41978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
420d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang    protected void setSwipingEnabled(boolean enabled) {
421d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang        mAppBridge.setSwipingEnabled(enabled);
42278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    }
42378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
424a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang    protected void notifyScreenNailChanged() {
425a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang        mAppBridge.notifyScreenNailChanged();
426a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang    }
427a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang
428a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li    protected void onPreviewTextureCopied() {
429a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li    }
43078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
43178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    //////////////////////////////////////////////////////////////////////////
43278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    //  The is the communication interface between the Camera Application and
43378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    //  the Gallery PhotoPage.
43478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    //////////////////////////////////////////////////////////////////////////
43578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
436a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li    class MyAppBridge extends AppBridge implements CameraScreenNail.Listener {
43778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        private CameraScreenNail mCameraScreenNail;
43878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        private Server mServer;
43978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
44078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
44178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public ScreenNail attachScreenNail() {
442a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang            if (mCameraScreenNail == null) {
443a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang                mCameraScreenNail = new CameraScreenNail(this);
444a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang            }
44578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            return mCameraScreenNail;
44678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
44778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
44878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
44978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public void detachScreenNail() {
45078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mCameraScreenNail = null;
45178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
45278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
45378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public CameraScreenNail getCameraScreenNail() {
45478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            return mCameraScreenNail;
45578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
45678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
45778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // Return true if the tap is consumed.
45878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
45978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public boolean onSingleTapUp(int x, int y) {
46078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            return ActivityBase.this.onSingleTapUp(x, y);
46178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
46278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
46378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // This is used to notify that the screen nail will be drawn in full screen
46478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        // or not in next draw() call.
46578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
46678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public void onFullScreenChanged(boolean full) {
46778b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            ActivityBase.this.onFullScreenChanged(full);
46878b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
46978b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
47078b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
47178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public void requestRender() {
47278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            getGLRoot().requestRender();
47378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
47478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
47578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        @Override
476a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li        public void onPreviewTextureCopied() {
477a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li            ActivityBase.this.onPreviewTextureCopied();
478a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li        }
479a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li
480a1fb83c0f18518013c3b1d4ab8c0f78a7bc0710fWu-cheng Li        @Override
48178b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        public void setServer(Server s) {
48278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            mServer = s;
48378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
48478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
48505e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong        @Override
48605e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong        public boolean isPanorama() {
48705e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong            return ActivityBase.this.isPanoramaActivity();
48805e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong        }
48905e0d1744d7325621170aff167cb65b7dfdf18f2Angus Kong
490f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang        private void setCameraRelativeFrame(Rect frame) {
491f3c71bf38a4f0c529d076ef93b2fae3aa59dbf4eChih-Chung Chang            if (mServer != null) mServer.setCameraRelativeFrame(frame);
49278b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
49378b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang
49478b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        private void switchWithCaptureAnimation(int offset) {
49578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang            if (mServer != null) mServer.switchWithCaptureAnimation(offset);
49678b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang        }
497d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang
498d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang        private void setSwipingEnabled(boolean enabled) {
499d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang            if (mServer != null) mServer.setSwipingEnabled(enabled);
500d03d34ac9f50857f38034749607ce07c161d5120Chih-Chung Chang        }
501a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang
502a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang        private void notifyScreenNailChanged() {
503a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang            if (mServer != null) mServer.notifyScreenNailChanged();
504a60436f0df6fc4189473b5ed27887edbba30312cChih-Chung Chang        }
50578b7bc5fe8e47bc422daf3b4e83cc7b241b210fdChih-Chung Chang    }
5064d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang}
507