Camera.java revision 0e841fe509c3b61ced7ddf4bee4728b382eae62f
1b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project/*
2b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
4b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * you may not use this file except in compliance with the License.
6b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * You may obtain a copy of the License at
7b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
8b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
10b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * See the License for the specific language governing permissions and
14b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * limitations under the License.
15b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */
16b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
17b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpackage com.android.camera;
18b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
19101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport com.android.camera.gallery.IAddImageCancelable;
20101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport com.android.camera.gallery.IImage;
21101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport com.android.camera.gallery.IImageList;
22101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
23b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.app.Activity;
240e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Linimport android.content.ActivityNotFoundException;
25b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.BroadcastReceiver;
26b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.ContentResolver;
27b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Context;
28b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Intent;
29b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.IntentFilter;
30b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.SharedPreferences;
31b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.pm.ActivityInfo;
32b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.Bitmap;
33b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.BitmapFactory;
34b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.Matrix;
35b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.drawable.Drawable;
36b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.hardware.Camera.PictureCallback;
37b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.hardware.Camera.Size;
38b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.location.Location;
39b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.location.LocationManager;
40b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.location.LocationProvider;
41b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.media.AudioManager;
42b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.media.ToneGenerator;
43b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.net.Uri;
44b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Bundle;
45b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Debug;
46b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Environment;
47b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Handler;
48b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Message;
49b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.SystemClock;
50b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.preference.PreferenceManager;
51b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.provider.MediaStore;
52b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.text.format.DateFormat;
53b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.util.Config;
54b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.util.Log;
55b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.KeyEvent;
56b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Menu;
57b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.MenuItem;
58b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.OrientationEventListener;
59b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.SurfaceHolder;
60b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.View;
61b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.ViewGroup;
62b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Window;
63b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.WindowManager;
640e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Linimport android.view.MenuItem.OnMenuItemClickListener;
65b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.AlphaAnimation;
66b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.Animation;
67b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.AnimationUtils;
68b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.ImageView;
69b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.Toast;
70b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
710e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Linimport java.io.File;
720e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Linimport java.io.FileNotFoundException;
730e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Linimport java.io.FileOutputStream;
740e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Linimport java.io.IOException;
750e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Linimport java.io.OutputStream;
760e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Linimport java.util.ArrayList;
770e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin
780e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin/**
790e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin * Activity of the Camera which used to see preview and take pictures.
800e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin */
81b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpublic class Camera extends Activity implements View.OnClickListener,
820e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback {
83b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
84b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final String TAG = "camera";
85b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
86b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final boolean DEBUG = false;
87b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final boolean DEBUG_TIME_OPERATIONS = DEBUG && false;
88b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
89b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int CROP_MSG = 1;
90b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int RESTART_PREVIEW = 3;
91b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int CLEAR_SCREEN_DELAY = 4;
92b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
93b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int SCREEN_DELAY = 2 * 60 * 1000;
94b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int FOCUS_BEEP_VOLUME = 100;
95b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
96b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SWITCH_TO_VIDEO = 0;
97b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SWITCH_TO_CAMERA = 1;
98b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_FLASH_SETTING = 2;
99b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_FLASH_AUTO = 3;
100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_FLASH_ON = 4;
101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_FLASH_OFF = 5;
102b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SETTINGS = 6;
103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_PHOTOS = 7;
104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_VIDEOS = 8;
105b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_SELECT_PHOTOS = 30;
106b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_NEW_PHOTO = 31;
107b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_GALLERY_PHOTO = 34;
108b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_GALLERY_VIDEO_PHOTO = 35;
109b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_CAMERA_DONE = 36;
110b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_CAMERA_VIDEO_DONE = 37;
111b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11287341536812081826656040ac81f8f386c6c1407Wu-cheng Li    private android.hardware.Camera.Parameters mParameters;
11387341536812081826656040ac81f8f386c6c1407Wu-cheng Li
11487341536812081826656040ac81f8f386c6c1407Wu-cheng Li    // The parameter strings to communicate with camera driver.
11587341536812081826656040ac81f8f386c6c1407Wu-cheng Li    public static final String PARM_WHITE_BALANCE = "whitebalance";
1162ac0387bbd6792187aeaacf10e40688f4260e316Wu-cheng Li    public static final String PARM_EFFECT = "effect";
11787341536812081826656040ac81f8f386c6c1407Wu-cheng Li    public static final String PARM_JPEG_QUALITY = "jpeg-quality";
11887341536812081826656040ac81f8f386c6c1407Wu-cheng Li    public static final String PARM_ROTATION = "rotation";
11987341536812081826656040ac81f8f386c6c1407Wu-cheng Li    public static final String PARM_GPS_LATITUDE = "gps-latitude";
12087341536812081826656040ac81f8f386c6c1407Wu-cheng Li    public static final String PARM_GPS_LONGITUDE = "gps-longitude";
12187341536812081826656040ac81f8f386c6c1407Wu-cheng Li    public static final String PARM_GPS_ALTITUDE = "gps-altitude";
12287341536812081826656040ac81f8f386c6c1407Wu-cheng Li    public static final String PARM_GPS_TIMESTAMP = "gps-timestamp";
1232ac0387bbd6792187aeaacf10e40688f4260e316Wu-cheng Li    public static final String SUPPORTED_WHITE_BALANCE = "whitebalance-values";
1242ac0387bbd6792187aeaacf10e40688f4260e316Wu-cheng Li    public static final String SUPPORTED_EFFECT = "effect-values";
12587341536812081826656040ac81f8f386c6c1407Wu-cheng Li
126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private OrientationEventListener mOrientationListener;
127b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mLastOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
128b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private SharedPreferences mPreferences;
129b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
130b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int IDLE = 1;
131b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int SNAPSHOT_IN_PROGRESS = 2;
132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int SNAPSHOT_COMPLETED = 3;
133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
134b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mStatus = IDLE;
135b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final String sTempCropFilename = "crop-temp";
136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
137b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private android.hardware.Camera mCameraDevice;
138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private VideoPreview mSurfaceView;
139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private SurfaceHolder mSurfaceHolder = null;
140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mOriginalViewFinderWidth, mOriginalViewFinderHeight;
142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mViewFinderWidth, mViewFinderHeight;
143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mPreviewing = false;
144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Capturer mCaptureObject;
146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ImageCapture mImageCapture = null;
147b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mPausing = false;
149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1509c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUS_NOT_STARTED = 0;
1519c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUSING = 1;
1529c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUSING_SNAP_ON_FINISH = 2;
1539c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUS_SUCCESS = 3;
1549c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUS_FAIL = 4;
1559c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private int mFocusState = FOCUS_NOT_STARTED;
156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1570e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin    private ContentResolver mContentResolver;
158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mDidRegister = false;
159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ArrayList<MenuItem> mGalleryItems = new ArrayList<MenuItem>();
161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private LocationManager mLocationManager = null;
163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ShutterButton mShutterButton;
165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Animation mFocusBlinkAnimation;
167b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private View mFocusIndicator;
16807c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin    private ImageView mGpsIndicator;
169b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ToneGenerator mFocusToneGenerator;
170b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ShutterCallback mShutterCallback = new ShutterCallback();
172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private RawPictureCallback mRawPictureCallback = new RawPictureCallback();
173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private AutoFocusCallback mAutoFocusCallback = new AutoFocusCallback();
174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mFocusStartTime;
175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mFocusCallbackTime;
176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mCaptureStartTime;
177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mShutterCallbackTime;
178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mRawPictureCallbackTime;
179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mPicturesRemaining;
18007c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin    private boolean mRecordLocation;
181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mKeepAndRestartPreview;
183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1849bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private boolean mIsImageCaptureIntent;
1850e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin
1869bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // mPostCaptureAlert, mLastPictureButton, mThumbController
1879bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // are non-null only if isImageCaptureIntent() is true.
188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private View mPostCaptureAlert;
1899bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private ImageView mLastPictureButton;
1909bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private ThumbnailController mThumbController;
191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Handler mHandler = new MainHandler();
193b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
194b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private interface Capturer {
195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Uri getLastCaptureUri();
196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        void onSnap();
1979a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        void dismissFreezeFrame();
198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
2000e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin    /**
2010e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin     * This Handler is used to post message back onto the main thread of the
2020e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin     * application
2030e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin     */
204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class MainHandler extends Handler {
205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void handleMessage(Message msg) {
207b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            switch (msg.what) {
208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case RESTART_PREVIEW: {
209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (mStatus == SNAPSHOT_IN_PROGRESS) {
2100e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        // We are still in the processing of taking the picture,
2110e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        // wait. This is strange.  Why are we polling?
2120e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        // TODO: remove polling
213b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mHandler.sendEmptyMessageDelayed(RESTART_PREVIEW, 100);
214b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } else if (mStatus == SNAPSHOT_COMPLETED){
2159a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                        mCaptureObject.dismissFreezeFrame();
216b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        hidePostCaptureAlert();
217b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
218b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
219b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
220b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
221b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case CLEAR_SCREEN_DELAY: {
2220e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    getWindow().clearFlags(
2230e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
225b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
226b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
227b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
228b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
229b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
230b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    LocationListener [] mLocationListeners = new LocationListener[] {
231b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            new LocationListener(LocationManager.GPS_PROVIDER),
232b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            new LocationListener(LocationManager.NETWORK_PROVIDER)
233b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
234b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
235b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
236b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
237b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
238b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onReceive(Context context, Intent intent) {
239b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            String action = intent.getAction();
240b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
241b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // SD card available
242b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                updateStorageHint(calculatePicturesRemaining());
243b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED) ||
244b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    action.equals(Intent.ACTION_MEDIA_CHECKING)) {
245b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // SD card unavailable
246b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mPicturesRemaining = MenuHelper.NO_STORAGE_ERROR;
247b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                updateStorageHint(mPicturesRemaining);
248b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) {
2490e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                Toast.makeText(Camera.this,
2500e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        getResources().getString(R.string.wait), 5000);
251b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) {
252b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                updateStorageHint();
253b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
254b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
255b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
256b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
2570e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin    private class LocationListener
2580e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            implements android.location.LocationListener {
259b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Location mLastLocation;
260b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean mValid = false;
261b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String mProvider;
262b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
263b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public LocationListener(String provider) {
264b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mProvider = provider;
265b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastLocation = new Location(mProvider);
266b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
267b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
268b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onLocationChanged(Location newLocation) {
2690e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            if (newLocation.getLatitude() == 0.0
2700e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    && newLocation.getLongitude() == 0.0) {
271b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // Hack to filter out 0.0,0.0 locations
272b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
273b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
27407c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            // If GPS is available before start camera, we won't get status
27507c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            // update so update GPS indicator when we receive data.
27607c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            if (mRecordLocation
27707c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                    && LocationManager.GPS_PROVIDER.equals(mProvider)) {
27807c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                mGpsIndicator.setVisibility(View.VISIBLE);
27907c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            }
280b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastLocation.set(newLocation);
281b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mValid = true;
282b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
283b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
284b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onProviderEnabled(String provider) {
285b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
286b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
287b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onProviderDisabled(String provider) {
288b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mValid = false;
289b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
290b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
2910e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        public void onStatusChanged(
2920e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                String provider, int status, Bundle extras) {
29307c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            switch(status) {
29407c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                case LocationProvider.OUT_OF_SERVICE:
29507c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                case LocationProvider.TEMPORARILY_UNAVAILABLE: {
29607c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                    mValid = false;
29707c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                    if (mRecordLocation &&
29807c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                            LocationManager.GPS_PROVIDER.equals(provider)) {
29907c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                        mGpsIndicator.setVisibility(View.INVISIBLE);
30007c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                    }
30107c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                    break;
30207c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                }
303b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
304b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
305b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
306b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public Location current() {
307b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return mValid ? mLastLocation : null;
308b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
309b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
310b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
311b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mImageSavingItem = false;
312b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3130e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin    private final class ShutterCallback
3140e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            implements android.hardware.Camera.ShutterCallback {
315b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onShutter() {
316b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) {
317b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mShutterCallbackTime = System.currentTimeMillis();
3180e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                Log.v(TAG, "Shutter lag was "
3190e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        + (mShutterCallbackTime - mCaptureStartTime) + " ms.");
320b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
321b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
322e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            // We are going to change the size of surface view and show captured
323de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // image. Set it to invisible now and set it back to visible in
324e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            // surfaceChanged() so that users won't see the image is resized on
325e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            // the screen.
326e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            mSurfaceView.setVisibility(View.INVISIBLE);
327b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Resize the SurfaceView to the aspect-ratio of the still image
328b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // and so that we can see the full image that was taken.
329e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            Size pictureSize = mParameters.getPictureSize();
330b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mSurfaceView.setAspectRatio(pictureSize.width, pictureSize.height);
331b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
333b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
334b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final class RawPictureCallback implements PictureCallback {
3350e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        public void onPictureTaken(
3360e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                byte [] rawData, android.hardware.Camera camera) {
3370e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            if (Config.LOGV) {
338b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "got RawPictureCallback...");
3390e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            }
340b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRawPictureCallbackTime = System.currentTimeMillis();
341b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) {
3420e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                Log.v(TAG, (mRawPictureCallbackTime - mShutterCallbackTime)
3430e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        + "ms elapsed between"
3440e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        + " ShutterCallback and RawPictureCallback.");
345b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
346b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
347b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
348b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
349b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final class JpegPictureCallback implements PictureCallback {
350b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Location mLocation;
351b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
352b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public JpegPictureCallback(Location loc) {
353b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLocation = loc;
354b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
355b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3560e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        public void onPictureTaken(
3570e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                byte [] jpegData, android.hardware.Camera camera) {
358de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            if (mPausing) {
359e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                return;
360e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            }
3610e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            if (Config.LOGV) {
362b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "got JpegPictureCallback...");
3630e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            }
364b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
365b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) {
366b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                long mJpegPictureCallback = System.currentTimeMillis();
3670e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                Log.v(TAG, (mJpegPictureCallback - mRawPictureCallbackTime)
3680e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        + "ms elapsed between"
3690e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        + " RawPictureCallback and JpegPictureCallback.");
370b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
371b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
372de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            if (jpegData != null) {
373de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                mImageCapture.storeImage(jpegData, camera, mLocation);
374de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            }
375b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
376b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStatus = SNAPSHOT_COMPLETED;
377b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
378b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mKeepAndRestartPreview) {
3790e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                long delay = 1500 - (
3800e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        System.currentTimeMillis() - mRawPictureCallbackTime);
3810e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                mHandler.sendEmptyMessageDelayed(
3820e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        RESTART_PREVIEW, Math.max(delay, 0));
383b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
384b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
385b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
386b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3870e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin    private final class AutoFocusCallback
3880e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            implements android.hardware.Camera.AutoFocusCallback {
3890e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        public void onAutoFocus(
3900e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                boolean focused, android.hardware.Camera camera) {
391b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) {
392b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mFocusCallbackTime = System.currentTimeMillis();
3930e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                Log.v(TAG, "Auto focus took "
3940e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        + (mFocusCallbackTime - mFocusStartTime) + " ms.");
395b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3970e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            if (mFocusState == FOCUSING_SNAP_ON_FINISH
3980e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    && mCaptureObject != null) {
3990e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                // Take the picture no matter focus succeeds or fails. No need
4000e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                // to play the AF sound if we're about to play the shutter
4010e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                // sound.
4029c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                mCaptureObject.onSnap();
4039c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                clearFocusState();
4049c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            } else if (mFocusState == FOCUSING) {
4059c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // User is half-pressing the focus key. Play the focus tone.
4069c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // Do not take the picture now.
4079c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                ToneGenerator tg = mFocusToneGenerator;
4080e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                if (tg != null) {
4090e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    tg.startTone(ToneGenerator.TONE_PROP_BEEP2);
4100e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                }
4119c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                if (focused) {
4129c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusState = FOCUS_SUCCESS;
4130e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                } else {
4149c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusState = FOCUS_FAIL;
4159c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                }
4169c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            } else if (mFocusState == FOCUS_NOT_STARTED) {
4179c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // User has released the focus key before focus completes.
4189c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // Do nothing.
419de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            }
420b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateFocusIndicator();
421b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
422b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
423b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
424b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class ImageCapture implements Capturer {
425b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
426b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private boolean mCancel = false;
427b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private boolean mCapturing = false;
428b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
429b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private Uri mLastContentUri;
430101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        private IAddImageCancelable mAddImageCancelable;
431b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
432b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bitmap mCaptureOnlyBitmap;
433b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
434b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        /** These member variables are used for various debug timings */
435b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private long mThreadTimeStart;
436b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private long mThreadTimeEnd;
437b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private long mWallTimeStart;
438b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private long mWallTimeEnd;
439b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
440b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
441b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public ImageCapture() {
442b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
443b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
444b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        /**
4450e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin         * This method sets whether or not we are capturing a picture. This
4460e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin         * method must be called with the ImageCapture.this lock held.
447b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         */
448b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void setCapturingLocked(boolean capturing) {
449b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCapturing = capturing;
450b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4529a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        public void dismissFreezeFrame() {
453b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStatus == SNAPSHOT_IN_PROGRESS) {
4540e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                // If we are still in the process of taking a picture,
4550e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                // then just post a message.
456b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mHandler.sendEmptyMessage(RESTART_PREVIEW);
457b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
458b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                restartPreview();
459b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
460b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
461b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
462b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private void startTiming() {
463b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mWallTimeStart = SystemClock.elapsedRealtime();
464b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mThreadTimeStart = Debug.threadCpuTimeNanos();
465b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
466b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
467b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private void stopTiming() {
468b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mThreadTimeEnd = Debug.threadCpuTimeNanos();
469b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mWallTimeEnd = SystemClock.elapsedRealtime();
470b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
471b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
472b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private void storeImage(byte[] data, Location loc) {
473b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
474b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
475b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    startTiming();
476b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
477b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                long dateTaken = System.currentTimeMillis();
478b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                String name = createName(dateTaken) + ".jpg";
479b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mLastContentUri = ImageManager.instance().addImage(
480b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        Camera.this,
481b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mContentResolver,
482b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        name,
483b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        "",
484b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        dateTaken,
4850e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        loc, // location for the database goes here
4860e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        0, // the dsp will use the right orientation so
4870e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                           // don't "double set it"
488b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        ImageManager.CAMERA_IMAGE_BUCKET_NAME,
489b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        name);
490b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mLastContentUri == null) {
491b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // this means we got an error
492b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCancel = true;
493b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
494b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (!mCancel) {
4950e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    mAddImageCancelable =
4960e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            ImageManager.instance().storeImage(mLastContentUri,
497b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            Camera.this, mContentResolver, 0, null, data);
498b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mAddImageCancelable.get();
499b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mAddImageCancelable = null;
500b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
501b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
502b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
503b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    stopTiming();
5040e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    Log.d(TAG, "Storing image took "
5050e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            + (mWallTimeEnd - mWallTimeStart) + " ms. "
5060e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            + "Thread time was "
5070e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            + ((mThreadTimeEnd - mThreadTimeStart) / 1000000)
5080e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            + " ms.");
509b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
510b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (Exception ex) {
511b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Exception while compressing image.", ex);
512b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
513b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
514b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5150e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        public void storeImage(
5160e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                byte[] data, android.hardware.Camera camera, Location loc) {
5179bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            boolean captureOnly = mIsImageCaptureIntent;
518b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
519b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (!captureOnly) {
520b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                storeImage(data, loc);
5210e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                sendBroadcast(new Intent(
5220e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        "com.android.camera.NEW_PICTURE", mLastContentUri));
523b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setLastPictureThumb(data, mCaptureObject.getLastCaptureUri());
5249a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                dismissFreezeFrame();
525b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
526b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                BitmapFactory.Options options = new BitmapFactory.Options();
527b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                options.inSampleSize = 4;
528b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
529b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
530b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    startTiming();
531b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
532b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5330e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                mCaptureOnlyBitmap = BitmapFactory.decodeByteArray(
5340e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        data, 0, data.length, options);
535b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
536b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
537b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    stopTiming();
5380e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    Log.d(TAG, "Decoded mCaptureOnly bitmap ("
5390e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            + mCaptureOnlyBitmap.getWidth() + "x"
5400e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            + mCaptureOnlyBitmap.getHeight() + " ) in "
5410e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            + (mWallTimeEnd - mWallTimeStart)
5420e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            + " ms. Thread time was "
5430e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            + ((mThreadTimeEnd - mThreadTimeStart) / 1000000)
5440e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            + " ms.");
545b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
546b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
547b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                showPostCaptureAlert();
548b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                cancelAutomaticPreviewRestart();
549b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
550b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
551b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCapturing = false;
552b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mPausing) {
553b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                closeCamera();
554b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
555b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
556b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5570e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        /**
558b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         * Initiate the capture of an image.
559b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         */
560b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void initiate(boolean captureOnly) {
56111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            if (mCameraDevice == null) {
56211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                return;
56311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            }
56411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
565b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCancel = false;
566b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCapturing = true;
56711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
568b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            capture(captureOnly);
569b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
570b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
571b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public Uri getLastCaptureUri() {
572b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return mLastContentUri;
573b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
574b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
575b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public Bitmap getLastBitmap() {
576b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return mCaptureOnlyBitmap;
577b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
578b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
579b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private void capture(boolean captureOnly) {
580b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPreviewing = false;
581b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCaptureOnlyBitmap = null;
582b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5830e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            final int latchedOrientation =
5840e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    ImageManager.roundOrientation(mLastOrientation + 90);
585b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
58607c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            Location loc = mRecordLocation ? getCurrentLocation() : null;
5870e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // Quality 75 has visible artifacts, and quality 90 looks great but
5880e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // the files begin to get large. 85 is a good compromise between
5890e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // the two.
59087341536812081826656040ac81f8f386c6c1407Wu-cheng Li            mParameters.set(PARM_JPEG_QUALITY, 85);
59187341536812081826656040ac81f8f386c6c1407Wu-cheng Li            mParameters.set(PARM_ROTATION, latchedOrientation);
592b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
59387341536812081826656040ac81f8f386c6c1407Wu-cheng Li            mParameters.remove(PARM_GPS_LATITUDE);
59487341536812081826656040ac81f8f386c6c1407Wu-cheng Li            mParameters.remove(PARM_GPS_LONGITUDE);
59587341536812081826656040ac81f8f386c6c1407Wu-cheng Li            mParameters.remove(PARM_GPS_ALTITUDE);
59687341536812081826656040ac81f8f386c6c1407Wu-cheng Li            mParameters.remove(PARM_GPS_TIMESTAMP);
597b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (loc != null) {
599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                double lat = loc.getLatitude();
600b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                double lon = loc.getLongitude();
601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                boolean hasLatLon = (lat != 0.0d) || (lon != 0.0d);
602b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
603b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (hasLatLon) {
604b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    String latString = String.valueOf(lat);
605b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    String lonString = String.valueOf(lon);
60687341536812081826656040ac81f8f386c6c1407Wu-cheng Li                    mParameters.set(PARM_GPS_LATITUDE,  latString);
60787341536812081826656040ac81f8f386c6c1407Wu-cheng Li                    mParameters.set(PARM_GPS_LONGITUDE, lonString);
608d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                    if (loc.hasAltitude()) {
6090e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        mParameters.set(PARM_GPS_ALTITUDE,
61087341536812081826656040ac81f8f386c6c1407Wu-cheng Li                                        String.valueOf(loc.getAltitude()));
611d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                    } else {
612d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                        // for NETWORK_PROVIDER location provider, we may have
613d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                        // no altitude information, but the driver needs it, so
614d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                        // we fake one.
61587341536812081826656040ac81f8f386c6c1407Wu-cheng Li                        mParameters.set(PARM_GPS_ALTITUDE,  "0");
616d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                    }
617b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (loc.getTime() != 0) {
618b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // Location.getTime() is UTC in milliseconds.
619b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // gps-timestamp is UTC in seconds.
620b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        long utcTimeSeconds = loc.getTime() / 1000;
62187341536812081826656040ac81f8f386c6c1407Wu-cheng Li                        mParameters.set(PARM_GPS_TIMESTAMP,
62287341536812081826656040ac81f8f386c6c1407Wu-cheng Li                                        String.valueOf(utcTimeSeconds));
623b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
624b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } else {
625b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    loc = null;
626b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
628b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
629b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.setParameters(mParameters);
630b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6310e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback,
6320e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    new JpegPictureCallback(loc));
633b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
634b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
635b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onSnap() {
636de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            if (mPausing) {
637e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                return;
638e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            }
6390e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            if (DEBUG_TIME_OPERATIONS) {
6400e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                mCaptureStartTime = System.currentTimeMillis();
6410e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            }
642b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6430e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // If we are already in the middle of taking a snapshot then we
6440e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // should just save
645b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // the image after we have returned from the camera service.
6460e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            if (mStatus == SNAPSHOT_IN_PROGRESS
6470e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    || mStatus == SNAPSHOT_COMPLETED) {
648b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mKeepAndRestartPreview = true;
649b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mHandler.sendEmptyMessage(RESTART_PREVIEW);
650b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
651b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
652b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6530e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // Don't check the filesystem here, we can't afford the latency.
6540e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // Instead, check the cached value which was calculated when the
6550e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // preview was restarted.
656b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mPicturesRemaining < 1) {
657b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                updateStorageHint(mPicturesRemaining);
658b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
659b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
660b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
661b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStatus = SNAPSHOT_IN_PROGRESS;
662b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
663b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mKeepAndRestartPreview = true;
664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            boolean getContentAction = mIsImageCaptureIntent;
666b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (getContentAction) {
667b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mImageCapture.initiate(true);
668b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mImageCapture.initiate(false);
670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
671b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
672de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
6739a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        private void clearLastBitmap() {
6749a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            if (mCaptureOnlyBitmap != null) {
6759a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                mCaptureOnlyBitmap.recycle();
6769a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                mCaptureOnlyBitmap = null;
6779a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            }
6789a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
679b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
680b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
681b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setLastPictureThumb(byte[] data, Uri uri) {
682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        BitmapFactory.Options options = new BitmapFactory.Options();
683b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        options.inSampleSize = 16;
6840e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        Bitmap lastPictureThumb =
6850e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                BitmapFactory.decodeByteArray(data, 0, data.length, options);
6869bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mThumbController.setData(uri, lastPictureThumb);
687b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
688b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6890e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin    private static String createName(long dateTaken) {
690b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString();
691b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
692b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6930e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin    public static Matrix getDisplayMatrix(Bitmap b, ImageView v) {
694b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Matrix m = new Matrix();
6950e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        float bw = b.getWidth();
6960e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        float bh = b.getHeight();
6970e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        float vw = v.getWidth();
6980e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        float vh = v.getHeight();
699b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        float scale, x, y;
7000e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        if (bw * vh > vw * bh) {
701b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            scale = vh / bh;
7020e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            x = (vw - scale * bw) * 0.5F;
703b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            y = 0;
704b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
705b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            scale = vw / bw;
706b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            x = 0;
7070e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            y = (vh - scale * bh) * 0.5F;
708b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
709b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        m.setScale(scale, scale, 0.5F, 0.5F);
710b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        m.postTranslate(x, y);
711b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return m;
712b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
713b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
714b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /** Called with the activity is first created. */
715b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
716b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onCreate(Bundle icicle) {
717b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreate(icicle);
718b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
7190e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        /*
7200e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin         * To reduce startup time, we open camera device in another thread.
7210e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin         * We make sure the camera is opened at the end of onCreate.
7220e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin         */
72311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        Thread openCameraThread = new Thread(new Runnable() {
72411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            public void run() {
72511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                mCameraDevice = android.hardware.Camera.open();
72611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            }
72711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        });
72811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        openCameraThread.start();
72911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
7300e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        // To reduce startup time, we run some service creation code in another
7310e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        // thread. We make sure the services are loaded at the end of
7320e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        // onCreate().
733b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Thread loadServiceThread = new Thread(new Runnable() {
734b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public void run() {
7350e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                mLocationManager = (LocationManager)
7360e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        getSystemService(Context.LOCATION_SERVICE);
7370e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                mOrientationListener =
7380e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        new OrientationEventListener(Camera.this) {
7390e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    @Override
740b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    public void onOrientationChanged(int orientation) {
7419c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                        // We keep the last known orientation. So if the user
7429c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                        // first orient the camera then point the camera to
7439c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                        // floor/sky, we still have the correct orientation.
7440e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        if (orientation != ORIENTATION_UNKNOWN) {
7459c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                            mLastOrientation = orientation;
7460e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        }
747b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
748b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                };
749b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
750b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
751b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        loadServiceThread.start();
752b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
753b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
754b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mContentResolver = getContentResolver();
755b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
756b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window win = getWindow();
757b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
758b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setContentView(R.layout.camera);
759b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
760b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceView = (VideoPreview) findViewById(R.id.camera_preview);
76107c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin        mGpsIndicator = (ImageView) findViewById(R.id.gps_indicator);
762b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
763b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // don't set mSurfaceHolder here. We have it set ONLY within
764b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // surfaceCreated / surfaceDestroyed, other parts of the code
765b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // assume that when it is set, the surface is also set.
766b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SurfaceHolder holder = mSurfaceView.getHolder();
767b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.addCallback(this);
768b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
769b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
7709bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mIsImageCaptureIntent = isImageCaptureIntent();
7719bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
7729bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsImageCaptureIntent)  {
7730e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            mLastPictureButton = (ImageView)
7740e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    findViewById(R.id.last_picture_button);
775b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastPictureButton.setOnClickListener(this);
7760e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            Drawable frame =
7770e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    getResources().getDrawable(R.drawable.frame_thumbnail);
7789bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController = new ThumbnailController(mLastPictureButton,
7799bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    frame, mContentResolver);
7809bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.loadData(ImageManager.getLastImageThumbPath());
781b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
782b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
783b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton = (ShutterButton) findViewById(R.id.shutter_button);
784b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setOnShutterButtonListener(this);
785b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
786b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mFocusIndicator = findViewById(R.id.focus_indicator);
7870e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        mFocusBlinkAnimation =
7880e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                AnimationUtils.loadAnimation(this, R.anim.auto_focus_blink);
789b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mFocusBlinkAnimation.setRepeatCount(Animation.INFINITE);
790b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mFocusBlinkAnimation.setRepeatMode(Animation.REVERSE);
791b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
792b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // We load the post_picture_panel layout only if it is needed.
7939bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsImageCaptureIntent) {
7940e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            ViewGroup cameraView = (ViewGroup) findViewById(R.id.camera);
795b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            getLayoutInflater().inflate(R.layout.post_picture_panel,
796b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                                        cameraView);
797b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostCaptureAlert = findViewById(R.id.post_picture_panel);
798b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
799b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
800b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // Make sure the services are loaded.
801b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
80211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            openCameraThread.join();
803b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            loadServiceThread.join();
804b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (InterruptedException ex) {
8050e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // ignore
806b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
807b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
808b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ImageManager.ensureOSXCompatibleFolder();
809b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
810b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
811b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
812b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onStart() {
813b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onStart();
814b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
815b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Thread t = new Thread(new Runnable() {
816b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public void run() {
817b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                final boolean storageOK = calculatePicturesRemaining() > 0;
818b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (!storageOK) {
819b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mHandler.post(new Runnable() {
820b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run() {
821b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            updateStorageHint(mPicturesRemaining);
822b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
823b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    });
824b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
825b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
826b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
827b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        t.start();
828b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
829b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
830b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onClick(View v) {
831b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (v.getId()) {
832b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case R.id.last_picture_button:
833087497fca0f048f0191cb02e2838819bf210a875Chih-Chung Chang            if (mStatus == IDLE && mFocusState == FOCUS_NOT_STARTED) {
834087497fca0f048f0191cb02e2838819bf210a875Chih-Chung Chang                viewLastImage();
835087497fca0f048f0191cb02e2838819bf210a875Chih-Chung Chang            }
836b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            break;
837b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case R.id.attach:
838b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            doAttach();
839b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            break;
840b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case R.id.cancel:
841b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            doCancel();
842b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
843b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
844b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
845b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doAttach() {
846de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        if (mPausing) {
847e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            return;
848e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
849b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bitmap bitmap = mImageCapture.getLastBitmap();
850b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
851b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String cropValue = null;
852b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Uri saveUri = null;
853b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
854b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bundle myExtras = getIntent().getExtras();
855b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (myExtras != null) {
856b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
857b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cropValue = myExtras.getString("crop");
858b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
859b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
860b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
861b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (cropValue == null) {
8620e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // First handle the no crop case -- just return the value.  If the
8630e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // caller specifies a "save uri" then write the data to it's
8640e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // stream. Otherwise, pass back a scaled down version of the bitmap
8650e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // directly in the extras.
866b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (saveUri != null) {
867b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                OutputStream outputStream = null;
868b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
869b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    outputStream = mContentResolver.openOutputStream(saveUri);
8700e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    bitmap.compress(Bitmap.CompressFormat.JPEG, 75,
8710e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            outputStream);
872b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    outputStream.close();
873b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
874b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    setResult(RESULT_OK);
875b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    finish();
876b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } catch (IOException ex) {
8770e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    // ignore exception
878b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } finally {
879b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (outputStream != null) {
880b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        try {
881b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            outputStream.close();
882b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        } catch (IOException ex) {
8830e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            // ignore exception
884b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
885b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
886b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
887b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
888b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                float scale = .5F;
889b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Matrix m = new Matrix();
890b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                m.setScale(scale, scale);
891b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
892b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                bitmap = Bitmap.createBitmap(bitmap, 0, 0,
893b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        bitmap.getWidth(),
894b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        bitmap.getHeight(),
895b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        m, true);
896b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
8970e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                setResult(RESULT_OK,
8980e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        new Intent("inline-data").putExtra("data", bitmap));
899b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                finish();
900b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
9010e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        } else {
9020e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // Save the image to a temp file and invoke the cropper
903b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri tempUri = null;
904b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            FileOutputStream tempStream = null;
905b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
906b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                File path = getFileStreamPath(sTempCropFilename);
907b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                path.delete();
908b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                tempStream = openFileOutput(sTempCropFilename, 0);
909b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                bitmap.compress(Bitmap.CompressFormat.JPEG, 75, tempStream);
910b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                tempStream.close();
911b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                tempUri = Uri.fromFile(path);
912b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (FileNotFoundException ex) {
913b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setResult(Activity.RESULT_CANCELED);
914b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                finish();
915b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
916b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (IOException ex) {
917b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setResult(Activity.RESULT_CANCELED);
918b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                finish();
919b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
920b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } finally {
921b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (tempStream != null) {
922b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    try {
923b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        tempStream.close();
924b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } catch (IOException ex) {
9250e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        // ignore exception
926b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
927b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
928b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
929b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
930b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Bundle newExtras = new Bundle();
9310e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            if (cropValue.equals("circle")) {
932b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                newExtras.putString("circleCrop", "true");
9330e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            }
9340e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            if (saveUri != null) {
935b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, saveUri);
9360e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            } else {
937b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                newExtras.putBoolean("return-data", true);
9380e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            }
939b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
940b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Intent cropIntent = new Intent();
941b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cropIntent.setClass(Camera.this, CropImage.class);
942b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cropIntent.setData(tempUri);
943b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cropIntent.putExtras(newExtras);
944b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
945b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            startActivityForResult(cropIntent, CROP_MSG);
946b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
947b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
948b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
949b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doCancel() {
950b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setResult(RESULT_CANCELED, new Intent());
951b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        finish();
952b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
953b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
954b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onShutterButtonFocus(ShutterButton button, boolean pressed) {
95511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if (mPausing) {
956e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            return;
957e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
958b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (button.getId()) {
959b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.shutter_button:
960b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doFocus(pressed);
961b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
962b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
963b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
964b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
965b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onShutterButtonClick(ShutterButton button) {
96611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if (mPausing) {
967e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            return;
968e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
969b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (button.getId()) {
970b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.shutter_button:
9719c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                doSnap();
972b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
973b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
974b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
975b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
976b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateStorageHint() {
977b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project      updateStorageHint(MenuHelper.calculatePicturesRemaining());
978b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
979b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
980b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private OnScreenHint mStorageHint;
981b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
982b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateStorageHint(int remaining) {
983b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String noStorageText = null;
984b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
985b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (remaining == MenuHelper.NO_STORAGE_ERROR) {
986b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            String state = Environment.getExternalStorageState();
987b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (state == Environment.MEDIA_CHECKING) {
988b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                noStorageText = getString(R.string.preparing_sd);
989b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
990b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                noStorageText = getString(R.string.no_storage);
991b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
992b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else if (remaining < 1) {
993b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            noStorageText = getString(R.string.not_enough_space);
994b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
995b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
996b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (noStorageText != null) {
997b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStorageHint == null) {
998b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint = OnScreenHint.makeText(this, noStorageText);
999b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
1000b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint.setText(noStorageText);
1001b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1002b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.show();
1003b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else if (mStorageHint != null) {
1004b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
1005b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
1006b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1007b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1008b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1009b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1010b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onResume() {
1011b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onResume();
1012b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
1013b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1014b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPausing = false;
1015b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mOrientationListener.enable();
101607c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin        mRecordLocation = mPreferences.getBoolean(
101707c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                "pref_camera_recordlocation_key", false);
101807c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin        mGpsIndicator.setVisibility(View.INVISIBLE);
1019b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1020b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // install an intent filter to receive SD card related events.
10210e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        IntentFilter intentFilter =
10220e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
1023b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
1024b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
1025b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
1026b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_CHECKING);
1027b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addDataScheme("file");
1028b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        registerReceiver(mReceiver, intentFilter);
1029b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mDidRegister = true;
1030b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1031b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mImageCapture = new ImageCapture();
1032b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1033b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        restartPreview();
1034b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
103507c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin        if (mRecordLocation) startReceivingLocationUpdates();
1036b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1037b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        updateFocusIndicator();
1038b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1039b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
10400e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            mFocusToneGenerator = new ToneGenerator(
10410e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    AudioManager.STREAM_SYSTEM, FOCUS_BEEP_VOLUME);
1042b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (RuntimeException e) {
10430e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            Log.w(TAG, "Exception caught while creating local tone generator: "
10440e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    + e);
1045b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mFocusToneGenerator = null;
1046b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1047b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1048b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static ImageManager.DataLocation dataLocation() {
1050b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return ImageManager.DataLocation.EXTERNAL;
1051b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1052b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1053b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1054b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onStop() {
1055b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        keep();
1056b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopPreview();
1057b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        closeCamera();
1058b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1059b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onStop();
1060b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1061b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1062b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1063b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    protected void onPause() {
1064b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        keep();
1065b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1066b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPausing = true;
1067b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mOrientationListener.disable();
1068b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1069b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopPreview();
1070b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1071b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (!mImageCapture.mCapturing) {
1072b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            closeCamera();
1073b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1074b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mDidRegister) {
1075b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            unregisterReceiver(mReceiver);
1076b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mDidRegister = false;
1077b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1078b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopReceivingLocationUpdates();
1079b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1080b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mFocusToneGenerator != null) {
1081b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mFocusToneGenerator.release();
1082b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mFocusToneGenerator = null;
1083b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1084b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10859bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsImageCaptureIntent) {
10869bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.storeData(ImageManager.getLastImageThumbPath());
10879bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
10889bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
1089b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mStorageHint != null) {
1090b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
1091b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
1092b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1093de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
10949a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        // If we are in an image capture intent and has taken
10959a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        // a picture, we just clear it in onPause.
10969a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mImageCapture.clearLastBitmap();
10979a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mImageCapture = null;
10989a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        hidePostCaptureAlert();
1099e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project
1100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPause();
1101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1102b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
11040e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin    protected void onActivityResult(
11050e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            int requestCode, int resultCode, Intent data) {
1106b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (requestCode) {
1107b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case CROP_MSG: {
1108b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Intent intent = new Intent();
1109b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (data != null) {
1110b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Bundle extras = data.getExtras();
1111b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (extras != null) {
1112b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        intent.putExtras(extras);
1113b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
1114b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1115b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setResult(resultCode, intent);
1116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                finish();
1117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                File path = getFileStreamPath(sTempCropFilename);
1119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                path.delete();
1120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
1122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1125b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void autoFocus() {
1127b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        updateFocusIndicator();
11289c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        if (mFocusState != FOCUSING && mFocusState != FOCUSING_SNAP_ON_FINISH) {
1129b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCameraDevice != null) {
1130b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
1131b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mFocusStartTime = System.currentTimeMillis();
1132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
11339c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                mFocusState = FOCUSING;
11349c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                mCameraDevice.autoFocus(mAutoFocusCallback);
1135b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1137b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11399c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private void clearFocusState() {
11409c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        mFocusState = FOCUS_NOT_STARTED;
1141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateFocusIndicator() {
1144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.post(new Runnable() {
1145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public void run() {
11469c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                if (mFocusState == FOCUS_SUCCESS) {
11479c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.setVisibility(View.VISIBLE);
1148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mFocusIndicator.clearAnimation();
11499c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                } else if (mFocusState == FOCUS_FAIL) {
11509c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.setVisibility(View.VISIBLE);
11519c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.startAnimation(mFocusBlinkAnimation);
1152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } else {
11539c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.setVisibility(View.GONE);
11549c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.clearAnimation();
1155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
1158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
1163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
1164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
1165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (keyCode) {
1167b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_BACK:
1168b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mStatus == SNAPSHOT_IN_PROGRESS) {
1169b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // ignore backs while we're taking a picture
1170b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
1171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
1173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_FOCUS:
1174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
117511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    doFocus(true);
1176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_CAMERA:
1179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
118011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    doSnap();
1181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_CENTER:
11840e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                // If we get a dpad center event without any focused view, move
11850e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                // the focus to the shutter button and press it.
1186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
11870e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    // Start auto-focus immediately to reduce shutter lag. After
11880e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    // the shutter button gets the focus, doFocus() will be
11890e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    // called again but it is fine.
119011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    doFocus(true);
119111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    if (mShutterButton.isInTouchMode()) {
119211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        mShutterButton.requestFocusFromTouch();
119311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    } else {
119411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        mShutterButton.requestFocus();
1195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
119611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    mShutterButton.setPressed(true);
1197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1201b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyDown(keyCode, event);
1202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1203b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
1206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (keyCode) {
1207b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_FOCUS:
1208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doFocus(false);
1209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1210b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyUp(keyCode, event);
1212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1213b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12149c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private void doSnap() {
12150e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        /*
12160e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin         * If the user has half-pressed the shutter and focus is completed, we
12170e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin         * can take the photo right away.
12180e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin         */
1219de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        if ((mFocusState == FOCUS_SUCCESS || mFocusState == FOCUS_FAIL)
12209c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                || !mPreviewing) {
1221b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // doesn't get set until the idler runs
1222b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCaptureObject != null) {
1223b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCaptureObject.onSnap();
1224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
12259c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            clearFocusState();
1226b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateFocusIndicator();
12278d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        } else if (mFocusState == FOCUSING) {
1228de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // Half pressing the shutter (i.e. the focus button event) will
1229de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // already have requested AF for us, so just request capture on
12309c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            // focus here.
12319c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            mFocusState = FOCUSING_SNAP_ON_FINISH;
12328d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        } else if (mFocusState == FOCUS_NOT_STARTED) {
12338d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project            // Focus key down event is dropped for some reasons. Just ignore.
1234b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1235b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1236b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1237b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doFocus(boolean pressed) {
12389c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        if (pressed) {  // Focus key down.
1239b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mPreviewing) {
1240b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                autoFocus();
1241b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (mCaptureObject != null) {
1242b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // Save and restart preview
1243b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCaptureObject.onSnap();
1244b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
12459c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        } else {  // Focus key up.
12469c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            if (mFocusState != FOCUSING_SNAP_ON_FINISH) {
12479c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // User releases half-pressed focus key.
12489c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                clearFocusState();
12499c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                updateFocusIndicator();
12509c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            }
1251b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1252b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1253b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1254b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
1255e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        mSurfaceView.setVisibility(View.VISIBLE);
1256b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // if we're creating the surface, start the preview as well.
1257b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean preview = holder.isCreating();
1258b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setViewFinder(w, h, preview);
1259de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mCaptureObject = mImageCapture;
1260b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1261b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1262b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceCreated(SurfaceHolder holder) {
1263b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = holder;
1264b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1265b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1266b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceDestroyed(SurfaceHolder holder) {
1267b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopPreview();
1268b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = null;
1269b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1270b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1271b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void closeCamera() {
1272b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraDevice != null) {
1273b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.release();
1274b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice = null;
1275b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPreviewing = false;
1276b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1277b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1278b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
127911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks    private boolean ensureCameraDevice() {
128011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if (mCameraDevice == null) {
128111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice = android.hardware.Camera.open();
128211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        }
128311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        return mCameraDevice != null;
128411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks    }
128511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
1286b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateLastImage() {
1287101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        IImageList list = ImageManager.instance().allImages(
1288b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            this,
1289b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mContentResolver,
1290b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            dataLocation(),
1291b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ImageManager.INCLUDE_IMAGES,
1292b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ImageManager.SORT_ASCENDING,
1293b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ImageManager.CAMERA_IMAGE_BUCKET_ID);
1294b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int count = list.getCount();
1295b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (count > 0) {
12960e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            IImage image = list.getImageAt(count - 1);
12979bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            Uri uri = image.fullSizeImageUri();
12989bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(uri, image.miniThumbBitmap());
1299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
13009bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(null, null);
1301b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1302b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        list.deactivate();
1303b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1304b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1305b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void restartPreview() {
1306b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        VideoPreview surfaceView = mSurfaceView;
1307b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1308b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // make sure the surfaceview fills the whole screen when previewing
1309b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        surfaceView.setAspectRatio(VideoPreview.DONT_CARE);
13100e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        setViewFinder(mOriginalViewFinderWidth, mOriginalViewFinderHeight,
13110e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                true);
1312b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mStatus = IDLE;
1313b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
13140e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        // Calculate this in advance of each shot so we don't add to shutter
13150e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        // latency. It's true that someone else could write to the SD card in
13160e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        // the mean time and fill it, but that could have happened between the
13170e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        // shutter press and saving the JPEG too.
13180e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin
13190e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        // TODO: The best longterm solution is to write a reserve file of
13200e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        //     maximum JPEG size, always let the user take a picture, and
13210e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        //     delete that file if needed to save the new photo.
1322b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        calculatePicturesRemaining();
1323b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
13249bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsImageCaptureIntent && !mThumbController.isUriValid()) {
1325b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateLastImage();
1326b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1327de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
13289bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsImageCaptureIntent) {
13299bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.updateDisplayIfNeeded();
1330b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1331b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1333b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setViewFinder(int w, int h, boolean startPreview) {
13340e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        if (mPausing) return;
1335b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
13360e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        if (mPreviewing && w == mViewFinderWidth && h == mViewFinderHeight) {
1337b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1338b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1339b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
13400e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        if (!ensureCameraDevice() ) return;
134111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
13420e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        if (mSurfaceHolder == null) return;
1343b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
13440e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        if (isFinishing()) return;
1345b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
13460e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        if (mPausing) return;
1347b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1348b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // remember view finder size
1349b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mViewFinderWidth = w;
1350b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mViewFinderHeight = h;
1351b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mOriginalViewFinderHeight == 0) {
1352b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mOriginalViewFinderWidth = w;
1353b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mOriginalViewFinderHeight = h;
1354b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1355b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
13560e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        if (startPreview == false) return;
1357b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
13580e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        // start the preview if we're asked to...
13590e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        //
136011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        // we want to start the preview and we're previewing already,
136111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        // stop the preview first (this will blank the screen).
13620e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        if (mPreviewing) stopPreview();
1363b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
136411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        // this blanks the screen if the surface changed, no-op otherwise
136511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        try {
136611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice.setPreviewDisplay(mSurfaceHolder);
136711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        } catch (IOException exception) {
136811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice.release();
136911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice = null;
137011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            // TODO: add more exception handling logic here
137111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            return;
137211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        }
1373b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
137411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        // request the preview size, the hardware may not honor it,
137511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        // if we depended on it we would have to query the size again
137611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        mParameters = mCameraDevice.getParameters();
137711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        mParameters.setPreviewSize(w, h);
137887341536812081826656040ac81f8f386c6c1407Wu-cheng Li
137987341536812081826656040ac81f8f386c6c1407Wu-cheng Li        // Set white balance parameter.
138087341536812081826656040ac81f8f386c6c1407Wu-cheng Li        String whiteBalance = mPreferences.getString(
138187341536812081826656040ac81f8f386c6c1407Wu-cheng Li                CameraSettings.KEY_WHITE_BALANCE,
138287341536812081826656040ac81f8f386c6c1407Wu-cheng Li                getString(R.string.pref_camera_whitebalance_default));
138387341536812081826656040ac81f8f386c6c1407Wu-cheng Li        mParameters.set(PARM_WHITE_BALANCE, whiteBalance);
138487341536812081826656040ac81f8f386c6c1407Wu-cheng Li
13852ac0387bbd6792187aeaacf10e40688f4260e316Wu-cheng Li        // Set effect parameter.
13862ac0387bbd6792187aeaacf10e40688f4260e316Wu-cheng Li        String effect = mPreferences.getString(
13872ac0387bbd6792187aeaacf10e40688f4260e316Wu-cheng Li                CameraSettings.KEY_EFFECT,
13882ac0387bbd6792187aeaacf10e40688f4260e316Wu-cheng Li                getString(R.string.pref_camera_effect_default));
13892ac0387bbd6792187aeaacf10e40688f4260e316Wu-cheng Li        mParameters.set(PARM_EFFECT, effect);
13902ac0387bbd6792187aeaacf10e40688f4260e316Wu-cheng Li
139111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        try {
139211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice.setParameters(mParameters);
139311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        } catch (IllegalArgumentException e) {
139411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            // Ignore this error, it happens in the simulator.
139511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        }
1396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
139711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        final long wallTimeStart = SystemClock.elapsedRealtime();
139811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        final long threadTimeStart = Debug.threadCpuTimeNanos();
1399f5e26bbc592503f28933941740c29070fa6222aeDave Sparks
140011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        final Object watchDogSync = new Object();
14010e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin
140211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        Thread watchDog = new Thread(new Runnable() {
140311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            public void run() {
14040e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                int nextWarning = 1;
140511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                while (true) {
140611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    try {
140711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        synchronized (watchDogSync) {
140811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                            watchDogSync.wait(1000);
1409b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
141011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    } catch (InterruptedException ex) {
141111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        //
1412b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
141311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    if (mPreviewing) break;
1414b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
14150e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    int delay = (int) (SystemClock.elapsedRealtime()
14160e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            - wallTimeStart) / 1000;
14170e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    if (delay >= nextWarning) {
141811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        if (delay < 120) {
14190e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            Log.e(TAG, "preview hasn't started yet in "
14200e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                                    + delay + " seconds");
142111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        } else {
14220e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            Log.e(TAG, "preview hasn't started yet in "
14230e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                                    + (delay / 60) + " minutes");
142411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        }
14250e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                        if (nextWarning < 60) {
14260e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            nextWarning <<= 1;
14270e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            if (nextWarning == 16) {
14280e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                                nextWarning = 15;
142911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                            }
143011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        } else {
14310e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                            nextWarning += 60;
143211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        }
143311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    }
143411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                }
1435f5e26bbc592503f28933941740c29070fa6222aeDave Sparks            }
143611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        });
143711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
143811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        watchDog.start();
143911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
14400e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        if (Config.LOGV) {
144111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            Log.v(TAG, "calling mCameraDevice.startPreview");
14420e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        }
144311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        try {
144411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice.startPreview();
144511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        } catch (Throwable e) {
14460e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            // TODO: change Throwable to IOException once
14470e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            //      android.hardware.Camera.startPreview properly declares
14480e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            //      that it throws IOException.
1449b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
145011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        mPreviewing = true;
1451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
145211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        synchronized (watchDogSync) {
145311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            watchDogSync.notify();
1454b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
145511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
145611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        long threadTimeEnd = Debug.threadCpuTimeNanos();
145711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        long wallTimeEnd = SystemClock.elapsedRealtime();
145811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if ((wallTimeEnd - wallTimeStart) > 3000) {
14590e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            Log.w(TAG, "startPreview() to " + (wallTimeEnd - wallTimeStart)
14600e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    + " ms. Thread time was"
146111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    + (threadTimeEnd - threadTimeStart) / 1000000 + " ms.");
1462b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1463b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1464b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1465b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void stopPreview() {
146611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if (mCameraDevice != null && mPreviewing) {
146711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice.stopPreview();
1468b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
146911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        mPreviewing = false;
14708d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        // If auto focus was in progress, it would have been canceled.
1471de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        clearFocusState();
1472b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1473b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1474b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    void gotoGallery() {
1475b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.gotoCameraImageGallery(this);
1476b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1477b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1478b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void viewLastImage() {
14799bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mThumbController.isUriValid()) {
14809bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            Uri targetUri = mThumbController.getUri();
14810e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            targetUri = targetUri.buildUpon().appendQueryParameter(
14820e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    "bucketId", ImageManager.CAMERA_IMAGE_BUCKET_ID).build();
1483b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Intent intent = new Intent(Intent.ACTION_VIEW, targetUri);
1484b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            intent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION,
1485b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
1486b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            intent.putExtra(MediaStore.EXTRA_FULL_SCREEN, true);
1487b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            intent.putExtra(MediaStore.EXTRA_SHOW_ACTION_ICONS, true);
1488b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            intent.putExtra("com.android.camera.ReviewMode", true);
1489b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1490b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1491b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                startActivity(intent);
14920e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            } catch (ActivityNotFoundException ex) {
1493b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // ignore.
1494b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1495b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
1496b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "Can't view last image.");
1497b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1498b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1499b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1500b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    void keep() {
1501b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCaptureObject != null) {
15029a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            mCaptureObject.dismissFreezeFrame();
1503b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
15040e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin    }
1505b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1506101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin    private IImage getImageForURI(Uri uri) {
1507101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        IImageList list = ImageManager.instance().allImages(
1508b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                this,
1509b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mContentResolver,
1510b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                dataLocation(),
1511b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                ImageManager.INCLUDE_IMAGES,
1512b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                ImageManager.SORT_ASCENDING);
1513101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        IImage image = list.getImageForUri(uri);
1514b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        list.deactivate();
1515b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return image;
1516b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1517b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1518b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1519b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void startReceivingLocationUpdates() {
1520b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mLocationManager != null) {
1521b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1522b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mLocationManager.requestLocationUpdates(
1523b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        LocationManager.NETWORK_PROVIDER,
1524b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        1000,
1525b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        0F,
1526b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mLocationListeners[1]);
1527b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (java.lang.SecurityException ex) {
1528b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // ok
1529b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (IllegalArgumentException ex) {
1530b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (Config.LOGD) {
1531b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.d(TAG, "provider does not exist " + ex.getMessage());
1532b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1533b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1534b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1535b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mLocationManager.requestLocationUpdates(
1536b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        LocationManager.GPS_PROVIDER,
1537b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        1000,
1538b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        0F,
1539b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mLocationListeners[0]);
1540b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (java.lang.SecurityException ex) {
1541b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // ok
1542b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (IllegalArgumentException ex) {
1543b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (Config.LOGD) {
1544b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.d(TAG, "provider does not exist " + ex.getMessage());
1545b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1546b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1547b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1548b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1549b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1550b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void stopReceivingLocationUpdates() {
1551b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mLocationManager != null) {
1552b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            for (int i = 0; i < mLocationListeners.length; i++) {
1553b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
1554b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mLocationManager.removeUpdates(mLocationListeners[i]);
1555b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } catch (Exception ex) {
1556b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // ok
1557b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1558b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1559b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1560b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1561b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1562b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Location getCurrentLocation() {
1563b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // go in best to worst order
1564b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int i = 0; i < mLocationListeners.length; i++) {
156507c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            Location l = mLocationListeners[i].current();
156607c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            if (l != null) return l;
1567b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
156807c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin        return null;
1569b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1570b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1571b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1572b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onOptionsMenuClosed(Menu menu) {
1573b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onOptionsMenuClosed(menu);
15749a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (mImageSavingItem) {
1575b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // save the image if we presented the "advanced" menu
1576b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // which happens if "menu" is pressed while in
1577b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // SNAPSHOT_IN_PROGRESS  or SNAPSHOT_COMPLETED modes
1578b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            keep();
1579b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mHandler.sendEmptyMessage(RESTART_PREVIEW);
1580b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1581b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1582b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1583b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1584b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onMenuOpened(int featureId, Menu menu) {
1585b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (featureId == Window.FEATURE_OPTIONS_PANEL) {
1586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStatus == SNAPSHOT_IN_PROGRESS) {
1587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                cancelAutomaticPreviewRestart();
1588b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1590b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onMenuOpened(featureId, menu);
1591b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1592b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1593b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1594b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onPrepareOptionsMenu(Menu menu) {
1595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPrepareOptionsMenu(menu);
1596b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1597b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int i = 1; i <= MenuHelper.MENU_ITEM_MAX; i++) {
1598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (i != MenuHelper.GENERIC_ITEM) {
1599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                menu.setGroupVisible(i, false);
1600b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1602b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1603b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mStatus == SNAPSHOT_IN_PROGRESS || mStatus == SNAPSHOT_COMPLETED) {
1604b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            menu.setGroupVisible(MenuHelper.IMAGE_SAVING_ITEM, true);
1605b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mImageSavingItem = true;
1606b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
1607b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            menu.setGroupVisible(MenuHelper.IMAGE_MODE_ITEM, true);
1608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mImageSavingItem = false;
1609b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1610b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1611b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
1612b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1613b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1614b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void cancelAutomaticPreviewRestart() {
1615b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mKeepAndRestartPreview = false;
1616b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(RESTART_PREVIEW);
1617b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1618b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1619b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean isImageCaptureIntent() {
1620b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String action = getIntent().getAction();
1621b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action));
1622b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1623b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1624b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void showPostCaptureAlert() {
16259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsImageCaptureIntent) {
1626b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostCaptureAlert.setVisibility(View.VISIBLE);
1627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            int[] pickIds = {R.id.attach, R.id.cancel};
16280e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            for (int id : pickIds) {
1629b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                View view = mPostCaptureAlert.findViewById(id);
1630b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                view.setOnClickListener(this);
1631b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Animation animation = new AlphaAnimation(0F, 1F);
1632b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                animation.setDuration(500);
1633b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                view.setAnimation(animation);
1634b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1635b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1636b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1637b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1638b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void hidePostCaptureAlert() {
16399bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsImageCaptureIntent) {
1640b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostCaptureAlert.setVisibility(View.INVISIBLE);
1641b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1642b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1643b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1644b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1645b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onCreateOptionsMenu(Menu menu) {
1646b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreateOptionsMenu(menu);
1647b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
16489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsImageCaptureIntent) {
1649b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // No options menu for attach mode.
1650b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
1651b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
1652b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            addBaseMenuItems(menu);
1653b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1654b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
1655b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1656b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1657b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    SelectedImageGetter mSelectedImageGetter =
1658b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        new SelectedImageGetter() {
1659101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            public IImage getCurrentImage() {
1660b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return getImageForURI(getCurrentImageUri());
1661b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1662b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public Uri getCurrentImageUri() {
1663b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                keep();
1664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return mCaptureObject.getLastCaptureUri();
1665b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1666b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        };
1667b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1668b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int calculatePicturesRemaining() {
1669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPicturesRemaining = MenuHelper.calculatePicturesRemaining();
1670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return mPicturesRemaining;
1671b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1672b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1673b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void addBaseMenuItems(Menu menu) {
1674b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.addSwitchModeMenuItem(menu, this, true);
1675b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
16760e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            MenuItem gallery = menu.add(
16770e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    MenuHelper.IMAGE_MODE_ITEM, MENU_GALLERY_PHOTOS, 0,
16780e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    R.string.camera_gallery_photos_text)
16790e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
1680b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                public boolean onMenuItemClick(MenuItem item) {
1681b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    gotoGallery();
1682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
1683b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1684b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            });
1685b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
1686b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
1687b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1688b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
16890e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin            MenuItem gallery = menu.add(
16900e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    MenuHelper.VIDEO_MODE_ITEM, MENU_GALLERY_VIDEOS, 0,
16910e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    R.string.camera_gallery_photos_text)
16920e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
1693b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                public boolean onMenuItemClick(MenuItem item) {
1694b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    gotoGallery();
1695b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
1696b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1697b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            });
1698b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
1699b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
1700b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1701b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
17020e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin        MenuItem item = menu.add(MenuHelper.GENERIC_ITEM, MENU_SETTINGS,
17030e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                0, R.string.settings)
17040e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin                .setOnMenuItemClickListener(new OnMenuItemClickListener() {
1705b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public boolean onMenuItemClick(MenuItem item) {
1706d53513404618b7e28f3d5726e481faeb051c80d9Wu-cheng Li                // Do not go to camera settings during capture.
1707d53513404618b7e28f3d5726e481faeb051c80d9Wu-cheng Li                if (mStatus == IDLE && mFocusState == FOCUS_NOT_STARTED) {
1708d53513404618b7e28f3d5726e481faeb051c80d9Wu-cheng Li                    Intent intent = new Intent();
1709d53513404618b7e28f3d5726e481faeb051c80d9Wu-cheng Li                    intent.setClass(Camera.this, CameraSettings.class);
1710d53513404618b7e28f3d5726e481faeb051c80d9Wu-cheng Li                    startActivity(intent);
1711d53513404618b7e28f3d5726e481faeb051c80d9Wu-cheng Li                }
1712b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1713b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1714b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
1715b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        item.setIcon(android.R.drawable.ic_menu_preferences);
1716b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1717b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project}
1718