ActivityBase.java revision 72fe79a040df8f01b03a39bec2473f7b0de8228d
14d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang/*
24d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * Copyright (C) 2009 The Android Open Source Project
34d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang *
44d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * Licensed under the Apache License, Version 2.0 (the "License");
54d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * you may not use this file except in compliance with the License.
64d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * You may obtain a copy of the License at
74d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang *
84d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang *      http://www.apache.org/licenses/LICENSE-2.0
94d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang *
104d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * Unless required by applicable law or agreed to in writing, software
114d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * distributed under the License is distributed on an "AS IS" BASIS,
124d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * See the License for the specific language governing permissions and
144d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang * limitations under the License.
154d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang */
164d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang
174d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Changpackage com.android.camera;
184d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang
197d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Millerimport android.app.KeyguardManager;
20c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.content.ContentResolver;
21892781804513066b68b4a2fa6f846e862dac252aOwen Linimport android.content.Context;
225df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Liimport android.content.Intent;
234c7b291018e08dbb4bc1712d95117a294fa1416cWu-cheng Liimport android.content.pm.ActivityInfo;
242eaabf9cca4528b01e414c384a039c10907c9d0bPin Tingimport android.content.res.Configuration;
25296d27772b9543d55820e1d24d900fea959f1b7aPin Tingimport android.hardware.Camera.Parameters;
26c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Liimport android.os.AsyncTask;
278608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Changimport android.os.Bundle;
287d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Millerimport android.util.Log;
291cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Liimport android.view.animation.DecelerateInterpolator;
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;
35892781804513066b68b4a2fa6f846e862dac252aOwen Lin
36892781804513066b68b4a2fa6f846e862dac252aOwen Linimport com.android.camera.ui.PopupManager;
37892781804513066b68b4a2fa6f846e862dac252aOwen Linimport com.android.camera.ui.RotateImageView;
38a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.app.AbstractGalleryActivity;
39a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.app.PhotoPage;
40bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Liimport com.android.gallery3d.app.PhotoPage.PageTapListener;
41a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.app.GalleryActionBar;
42bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Liimport com.android.gallery3d.app.StateManager;
43a6b966047b6215b02c502a3f143106070abf6009Angus Kongimport com.android.gallery3d.util.MediaSetUtils;
444d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang
45aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Liimport java.io.File;
46aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
4777c1cdc8f2cda250b1db842204efb49f87e094aeChih-Chung Chang/**
487673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li * Superclass of Camera and VideoCamera activities.
4977c1cdc8f2cda250b1db842204efb49f87e094aeChih-Chung Chang */
50a6b966047b6215b02c502a3f143106070abf6009Angus Kongabstract public class ActivityBase extends AbstractGalleryActivity
518a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        implements CameraScreenNail.PositionChangedListener,
52bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li                View.OnLayoutChangeListener, PageTapListener {
53a6b966047b6215b02c502a3f143106070abf6009Angus Kong
547d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    private static final String TAG = "ActivityBase";
557d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    private static boolean LOGV = false;
56c38faeb66a3f2cc96e4c5e951228d9b01e12edb3Chih-Chung Chang    private static final int CAMERA_APP_VIEW_TOGGLE_TIME = 100;  // milliseconds
575df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    private int mResultCodeForTesting;
585df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    private Intent mResultDataForTesting;
594edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    private OnScreenHint mStorageHint;
601cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    private UpdateCameraAppView mUpdateCameraAppView;
611cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    private HideCameraAppView mHideCameraAppView;
62bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    private View mSingleTapArea;
63a6b966047b6215b02c502a3f143106070abf6009Angus Kong
64c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    // The bitmap of the last captured picture thumbnail and the URI of the
65c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    // original picture.
66c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected Thumbnail mThumbnail;
67c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    // An imageview showing showing the last captured picture thumbnail.
68c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected RotateImageView mThumbnailView;
698a674bebfba0c4dd4b01018276d20f198f65f19eWu-cheng Li    protected int mThumbnailViewWidth; // layout width of the thumbnail
70c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected AsyncTask<Void, Void, Thumbnail> mLoadThumbnailTask;
71475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected boolean mOpenCameraFail;
72475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected boolean mCameraDisabled;
73475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected CameraManager.CameraProxy mCameraDevice;
74296d27772b9543d55820e1d24d900fea959f1b7aPin Ting    protected Parameters mParameters;
755c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li    // The activity is paused. The classes that extend this class should set
765c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li    // mPaused the first thing in onResume/onPause.
775c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li    protected boolean mPaused;
78a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected GalleryActionBar mActionBar;
79475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting
80475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    // multiple cameras support
81475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected int mNumberOfCameras;
82475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected int mCameraId;
83475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting
84a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected CameraScreenNail mCameraScreenNail; // This shows camera preview.
85a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // The view containing only camera related widgets like control panel,
86a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // indicator bar, focus indicator and etc.
87a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected View mCameraAppView;
881cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    protected boolean mShowCameraAppView = true;
89a6b966047b6215b02c502a3f143106070abf6009Angus Kong
90475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    protected class CameraOpenThread extends Thread {
91475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        @Override
92475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        public void run() {
93475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            try {
94475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mCameraDevice = Util.openCamera(ActivityBase.this, mCameraId);
95296d27772b9543d55820e1d24d900fea959f1b7aPin Ting                mParameters = mCameraDevice.getParameters();
96475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            } catch (CameraHardwareException e) {
97475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mOpenCameraFail = true;
98475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            } catch (CameraDisabledException e) {
99475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting                mCameraDisabled = true;
100475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting            }
101475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting        }
102475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting    }
1035df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1044d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    @Override
1058608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    public void onCreate(Bundle icicle) {
1062eaabf9cca4528b01e414c384a039c10907c9d0bPin Ting        if (getResources().getConfiguration().orientation
1072eaabf9cca4528b01e414c384a039c10907c9d0bPin Ting                == Configuration.ORIENTATION_LANDSCAPE) {
1084c7b291018e08dbb4bc1712d95117a294fa1416cWu-cheng Li            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
109d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang        } else {
110d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
1114c7b291018e08dbb4bc1712d95117a294fa1416cWu-cheng Li        }
112e5b6a36e64ef2c2cb1435c138a5fc179e9a6bc9aWu-cheng Li        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
1136a4a72b643929701c5d7c8b68b91d762c7277c20Wu-cheng Li        super.disableToggleStatusBar();
1148608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang        super.onCreate(icicle);
1158608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    }
1168608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang
1178608b577921acf67a5a7b7968cb3633b8f94714dChih-Chung Chang    @Override
1187d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    protected void onPause() {
1195c17d7a077acd1f84bdcb7579f7d02a1094602bcWu-cheng Li        super.onPause();
1207d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller        if (LOGV) Log.v(TAG, "onPause");
121aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        saveThumbnailToFile();
1224edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong
123c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mLoadThumbnailTask != null) {
124c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask.cancel(true);
125c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask = null;
126c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
127c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
1284edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (mStorageHint != null) {
1294edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.cancel();
1304edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint = null;
1314edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
1327d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    }
1337d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
1347d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller    @Override
13572fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li    public void setContentView(int layoutResID) {
13672fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        // Set a theme with action bar. It is not specified in manifest because
13772fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        // we want to hide it by default. setTheme must happen before
13872fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        // setContentView.
13972fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        setTheme(android.R.style.Theme_Holo);
14072fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
14172fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
14272fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li
14372fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        super.setContentView(layoutResID);
14472fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        // getActionBar() should be after setContentView
14572fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        mActionBar = new GalleryActionBar(this);
14672fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li        mActionBar.hide();
14772fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li    }
14872fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li
14972fe79a040df8f01b03a39bec2473f7b0de8228dWu-cheng Li    @Override
1504d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    public boolean onSearchRequested() {
1514d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang        return false;
1524d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang    }
1537673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li
1547673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    @Override
1557673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    public boolean onKeyDown(int keyCode, KeyEvent event) {
1567673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        // Prevent software keyboard or voice search from showing up.
1577673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        if (keyCode == KeyEvent.KEYCODE_SEARCH
1587673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li                || keyCode == KeyEvent.KEYCODE_MENU) {
1597673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li            if (event.isLongPress()) return true;
1607673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        }
1617673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li
1627673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li        return super.onKeyDown(keyCode, event);
1637673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li    }
1645df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1655df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    protected void setResultEx(int resultCode) {
1665df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultCodeForTesting = resultCode;
1675df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        setResult(resultCode);
1685df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
1695df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1705df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    protected void setResultEx(int resultCode, Intent data) {
1715df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultCodeForTesting = resultCode;
1725df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        mResultDataForTesting = data;
1735df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        setResult(resultCode, data);
1745df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
1755df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1765df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    public int getResultCode() {
1775df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        return mResultCodeForTesting;
1785df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
1795df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li
1805df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    public Intent getResultData() {
1815df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li        return mResultDataForTesting;
1825df067af93e6b386167f11cdf12701b7905ee444Wu-cheng Li    }
1835f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang
1845f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    @Override
1855f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    protected void onDestroy() {
1865f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang        PopupManager.removeInstance(this);
1875f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang        super.onDestroy();
1885f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wang    }
1897d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller
19024e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li    @Override
19124e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li    public boolean onCreateOptionsMenu(Menu menu) {
19224e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li        super.onCreateOptionsMenu(menu);
19324e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li        return getStateManager().createOptionsMenu(menu);
19424e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li    }
19524e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li
1964edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    protected void updateStorageHint(long storageSpace) {
1974edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        String message = null;
1984edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (storageSpace == Storage.UNAVAILABLE) {
1994edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.no_storage);
2004edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace == Storage.PREPARING) {
2014edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.preparing_sd);
2024edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace == Storage.UNKNOWN_SIZE) {
2034edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.access_sd_fail);
2044edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (storageSpace < Storage.LOW_STORAGE_THRESHOLD) {
2054edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            message = getString(R.string.spaceIsLow_content);
2064edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
2074edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong
2084edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        if (message != null) {
2094edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            if (mStorageHint == null) {
2104edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong                mStorageHint = OnScreenHint.makeText(this, message);
2114edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            } else {
2124edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong                mStorageHint.setText(message);
2134edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            }
2144edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.show();
2154edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        } else if (mStorageHint != null) {
2164edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint.cancel();
2174edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong            mStorageHint = null;
2184edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong        }
2194edaf0cbbb5d9cfeae786b6fd0560240947f6585Angus Kong    }
220c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
221c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    private void updateThumbnailView() {
222c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mThumbnail != null) {
223c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setBitmap(mThumbnail.getBitmap());
224c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setVisibility(View.VISIBLE);
225c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        } else {
226c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setBitmap(null);
227c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnailView.setVisibility(View.GONE);
228c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
229c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
230c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
231c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    protected void getLastThumbnail() {
232c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        mThumbnail = ThumbnailHolder.getLastThumbnail(getContentResolver());
233c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // Suppose users tap the thumbnail view, go to the gallery, delete the
234c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // image, and coming back to the camera. Thumbnail file will be invalid.
235c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // Since the new thumbnail will be loaded in another thread later, the
236c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        // view should be set to gone to prevent from opening the invalid image.
237c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        updateThumbnailView();
238c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        if (mThumbnail == null) {
239c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mLoadThumbnailTask = new LoadThumbnailTask().execute();
240c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
241c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
242c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
243aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    private class LoadThumbnailTask extends AsyncTask<Void, Void, Thumbnail> {
244c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        @Override
245c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        protected Thumbnail doInBackground(Void... params) {
246c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            // Load the thumbnail from the file.
247c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            ContentResolver resolver = getContentResolver();
248c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            Thumbnail t = Thumbnail.getLastThumbnailFromFile(getFilesDir(), resolver);
249c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
250c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            if (isCancelled()) return null;
251c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
252c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            if (t == null) {
253c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li                // Load the thumbnail from the media provider.
254c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li                t = Thumbnail.getLastThumbnailFromContentResolver(resolver);
255c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            }
256c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            return t;
257c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
258c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li
259c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        @Override
260c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        protected void onPostExecute(Thumbnail thumbnail) {
261c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            mThumbnail = thumbnail;
262c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li            updateThumbnailView();
263c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li        }
264c24a2a83df9b54297995c5270d015bb7fdd85fabWu-cheng Li    }
265aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
2666899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting    protected void gotoGallery() {
26771bf9ebe0f207c1af741e3b76d84dde1358faa1bWu-cheng Li        // TODO: remove this after panorama has swipe UI.
26871bf9ebe0f207c1af741e3b76d84dde1358faa1bWu-cheng Li        if (getStateManager().getStateCount() > 0) {
26971bf9ebe0f207c1af741e3b76d84dde1358faa1bWu-cheng Li            PhotoPage photoPage = (PhotoPage) getStateManager().getTopState();
27071bf9ebe0f207c1af741e3b76d84dde1358faa1bWu-cheng Li            // Move the next picture with capture animation. "1" means next.
27171bf9ebe0f207c1af741e3b76d84dde1358faa1bWu-cheng Li            photoPage.switchWithCaptureAnimation(1);
27271bf9ebe0f207c1af741e3b76d84dde1358faa1bWu-cheng Li        } else {
27371bf9ebe0f207c1af741e3b76d84dde1358faa1bWu-cheng Li            Util.viewUri(mThumbnail.getUri(), this);
27471bf9ebe0f207c1af741e3b76d84dde1358faa1bWu-cheng Li        }
2756899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting    }
2766899a30e3a89ad4b455978140682d5ba871c1b33Pin Ting
277aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    protected void saveThumbnailToFile() {
278aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        if (mThumbnail != null && !mThumbnail.fromFile()) {
279aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            new SaveThumbnailTask().execute(mThumbnail);
280aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        }
281aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    }
282aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li
283aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    private class SaveThumbnailTask extends AsyncTask<Thumbnail, Void, Void> {
284aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        @Override
285aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        protected Void doInBackground(Thumbnail... params) {
286aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            final int n = params.length;
287aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            final File filesDir = getFilesDir();
288aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            for (int i = 0; i < n; i++) {
289aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li                params[i].saveLastThumbnailToFile(filesDir);
290aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            }
291aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li            return null;
292aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li        }
293aef5310d25537494679f9ec6b9d7a1a9cb60887dWu-cheng Li    }
294a6b966047b6215b02c502a3f143106070abf6009Angus Kong
295a6b966047b6215b02c502a3f143106070abf6009Angus Kong    // Call this after setContentView.
296a6b966047b6215b02c502a3f143106070abf6009Angus Kong    protected void createCameraScreenNail(boolean getPictures) {
297a6b966047b6215b02c502a3f143106070abf6009Angus Kong        mCameraAppView = findViewById(R.id.camera_app_root);
298a6b966047b6215b02c502a3f143106070abf6009Angus Kong        Bundle data = new Bundle();
299a6b966047b6215b02c502a3f143106070abf6009Angus Kong        String path = "/local/all/";
300a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // Intent mode does not show camera roll. Use 0 as a work around for
301a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // invalid bucket id.
302a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // TODO: add support of empty media set in gallery.
303a6b966047b6215b02c502a3f143106070abf6009Angus Kong        path += (getPictures ? MediaSetUtils.CAMERA_BUCKET_ID : "0");
304a6b966047b6215b02c502a3f143106070abf6009Angus Kong        data.putString(PhotoPage.KEY_MEDIA_SET_PATH, path);
305a6b966047b6215b02c502a3f143106070abf6009Angus Kong        data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, path);
306a6b966047b6215b02c502a3f143106070abf6009Angus Kong
307a6b966047b6215b02c502a3f143106070abf6009Angus Kong        // Send a CameraScreenNail to gallery to enable the camera preview.
308a6b966047b6215b02c502a3f143106070abf6009Angus Kong        CameraScreenNailHolder holder = new CameraScreenNailHolder(this);
309a6b966047b6215b02c502a3f143106070abf6009Angus Kong        data.putParcelable(PhotoPage.KEY_SCREENNAIL_HOLDER, holder);
310a6b966047b6215b02c502a3f143106070abf6009Angus Kong        getStateManager().startState(PhotoPage.class, data);
311a6b966047b6215b02c502a3f143106070abf6009Angus Kong        mCameraScreenNail = holder.getCameraScreenNail();
312a6b966047b6215b02c502a3f143106070abf6009Angus Kong        mCameraScreenNail.setPositionChangedListener(this);
313a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
314a6b966047b6215b02c502a3f143106070abf6009Angus Kong
3151cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    private class HideCameraAppView implements Runnable {
3161cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        @Override
3171cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        public void run() {
3181cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            mCameraAppView.setVisibility(View.GONE);
3191cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li        }
3201cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    }
321a6b966047b6215b02c502a3f143106070abf6009Angus Kong    private class UpdateCameraAppView implements Runnable {
322a6b966047b6215b02c502a3f143106070abf6009Angus Kong        @Override
323a6b966047b6215b02c502a3f143106070abf6009Angus Kong        public void run() {
3241cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            if (mShowCameraAppView) {
325a6b966047b6215b02c502a3f143106070abf6009Angus Kong                mCameraAppView.setVisibility(View.VISIBLE);
326c38faeb66a3f2cc96e4c5e951228d9b01e12edb3Chih-Chung Chang                mCameraAppView.animate()
327c38faeb66a3f2cc96e4c5e951228d9b01e12edb3Chih-Chung Chang                        .setDuration(CAMERA_APP_VIEW_TOGGLE_TIME)
328c38faeb66a3f2cc96e4c5e951228d9b01e12edb3Chih-Chung Chang                        .withLayer().alpha(1);
3291cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            } else {
330c38faeb66a3f2cc96e4c5e951228d9b01e12edb3Chih-Chung Chang                mCameraAppView.animate()
331c38faeb66a3f2cc96e4c5e951228d9b01e12edb3Chih-Chung Chang                        .setDuration(CAMERA_APP_VIEW_TOGGLE_TIME)
332c38faeb66a3f2cc96e4c5e951228d9b01e12edb3Chih-Chung Chang                        .withLayer().alpha(0).withEndAction(mHideCameraAppView);
333a6b966047b6215b02c502a3f143106070abf6009Angus Kong            }
334a6b966047b6215b02c502a3f143106070abf6009Angus Kong        }
335a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
336a6b966047b6215b02c502a3f143106070abf6009Angus Kong
337a6b966047b6215b02c502a3f143106070abf6009Angus Kong    @Override
3381cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li    public void onPositionChanged(int x, int y, int width, int height, boolean visible) {
339a6b966047b6215b02c502a3f143106070abf6009Angus Kong        if (!mPaused && !isFinishing()) {
3401cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            View rootView = (View) getGLRoot();
3411cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            int rootWidth = rootView.getWidth();
3421cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            int rootHeight = rootView.getHeight();
3431cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            boolean showCameraAppView;
3441cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            // Check if the camera preview is in the center.
3451cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            if (visible && (x == 0 && width == rootWidth) ||
3461cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                    (y == 0 && height == rootHeight && Math.abs(x - (rootWidth - width) / 2) <= 1)) {
3471cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                showCameraAppView = true;
348a6b966047b6215b02c502a3f143106070abf6009Angus Kong            } else {
3491cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                showCameraAppView = false;
3501cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            }
3511cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li
3521cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li            if (mShowCameraAppView != showCameraAppView) {
3531cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                mShowCameraAppView = showCameraAppView;
3541cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                // Initialize the animation.
3551cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                if (mUpdateCameraAppView == null) {
3561cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                    mUpdateCameraAppView = new UpdateCameraAppView();
3571cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                    mHideCameraAppView = new HideCameraAppView();
358c38faeb66a3f2cc96e4c5e951228d9b01e12edb3Chih-Chung Chang                    mCameraAppView.animate()
359c38faeb66a3f2cc96e4c5e951228d9b01e12edb3Chih-Chung Chang                        .setInterpolator(new DecelerateInterpolator());
3601cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                }
3611cc3a3466c8e9f30f13b81a88d8b2f31050c599cWu-cheng Li                runOnUiThread(mUpdateCameraAppView);
362a6b966047b6215b02c502a3f143106070abf6009Angus Kong            }
363a6b966047b6215b02c502a3f143106070abf6009Angus Kong        }
364a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
365a6b966047b6215b02c502a3f143106070abf6009Angus Kong
366a6b966047b6215b02c502a3f143106070abf6009Angus Kong    @Override
367a6b966047b6215b02c502a3f143106070abf6009Angus Kong    public GalleryActionBar getGalleryActionBar() {
368a6b966047b6215b02c502a3f143106070abf6009Angus Kong        return mActionBar;
369a6b966047b6215b02c502a3f143106070abf6009Angus Kong    }
3708a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li
3718a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li    // Preview frame layout has changed. Move the preview to the center of the
3728a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li    // layout.
3738a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li    @Override
3748a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li    public void onLayoutChange(View v, int left, int top, int right, int bottom,
3758a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li            int oldLeft, int oldTop, int oldRight, int oldBottom) {
3768a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        // Find out the left and top of the preview frame layout relative to GL
3778a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        // root view.
3788a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        View root = (View) getGLRoot();
3798a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        int[] rootLocation = new int[2];
3808a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        int[] viewLocation = new int[2];
3818a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        root.getLocationInWindow(rootLocation);
3828a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        v.getLocationInWindow(viewLocation);
3838a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        int relativeLeft = viewLocation[0] - rootLocation[0];
3848a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        int relativeTop = viewLocation[1] - rootLocation[1];
3858a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li
3868a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        // Calculate the scale ratio between preview frame layout and GL root
3878a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        // view.
3888a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        int width = root.getWidth();
3898a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        int height = root.getHeight();
3908a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        float scale = Math.max((float) (right - left) / width,
3918a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li                (float) (bottom - top) / height);
3928a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        float scalePx = width / 2f;
3938a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        float scalePy = height / 2f;
3948a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li
3958a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        // Calculate the translate distance.
3968a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        float translateX = relativeLeft + (right - left - width) / 2f;
3978a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        float translateY = relativeTop + (bottom - top - height) / 2f;
3988a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li
3998a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li        mCameraScreenNail.setMatrix(scale, scalePx, scalePy, translateX, translateY);
4008a79ddc5827de54a33d8fbef0e467da2266342cbWu-cheng Li    }
401bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
402bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    protected void setSingleTapUpListener(View singleTapArea) {
403bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        PhotoPage photoPage = (PhotoPage) getStateManager().getTopState();
404bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        photoPage.setPageTapListener(this);
405bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        mSingleTapArea = singleTapArea;
406bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    }
407bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
408bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    // Single tap up from PhotoPage.
409bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    @Override
410bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    public boolean onSingleTapUp(int x, int y) {
411bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        // Camera control is invisible. Ignore.
412bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        if (!mShowCameraAppView) return false;
413bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
414bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        int[] relativeLocation = Util.getRelativeLocation((View) getGLRoot(),
415bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li                mSingleTapArea);
416bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        x -= relativeLocation[0];
417bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        y -= relativeLocation[1];
418bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        if (x >= 0 && x < mSingleTapArea.getWidth() && y >= 0
419bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li                && y < mSingleTapArea.getHeight()) {
420bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li            onSingleTapUp(mSingleTapArea, x, y);
421bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li            return true;
422bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        }
423bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li        return false;
424bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    }
425bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li
426bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    protected void onSingleTapUp(View view, int x, int y) {
427bfaab736a344641a63170ebdcd9d5377779d3a15Wu-cheng Li    }
4284d2aefbe7c108bae9e4ae735c7cd230792201098Chih-Chung Chang}
429