Camera.java revision 9a379bd668227d3dcea30312025f304fd248f6e3
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
19b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.BufferedInputStream;
20b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.BufferedOutputStream;
21b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.DataInputStream;
22b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.DataOutputStream;
23b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.File;
24b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.FileInputStream;
25b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.FileNotFoundException;
26b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.FileOutputStream;
27b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.IOException;
28b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.OutputStream;
29b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.util.ArrayList;
30b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
31b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.app.Activity;
32b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.app.ProgressDialog;
33b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.BroadcastReceiver;
34b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.ContentResolver;
35b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Context;
36b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Intent;
37b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.IntentFilter;
38b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.SharedPreferences;
39b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.pm.ActivityInfo;
40b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.res.AssetFileDescriptor;
41b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.res.Resources;
42b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.Bitmap;
43b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.BitmapFactory;
44b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.Matrix;
45b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.drawable.BitmapDrawable;
46b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.drawable.Drawable;
47b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.drawable.LayerDrawable;
48b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.drawable.TransitionDrawable;
49b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.hardware.Camera.PictureCallback;
50b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.hardware.Camera.Size;
51b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.location.Location;
52b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.location.LocationManager;
53b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.location.LocationProvider;
54b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.media.AudioManager;
55b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.media.MediaPlayer;
56b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.media.ToneGenerator;
57b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.net.Uri;
58b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Bundle;
59b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Debug;
60b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Environment;
61b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Handler;
62b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Message;
63b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.SystemClock;
64b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.preference.PreferenceManager;
65b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.provider.MediaStore;
66b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.text.format.DateFormat;
67b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.util.Config;
68b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.util.Log;
69b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.KeyEvent;
70b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Menu;
71b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.MenuItem;
72b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.MenuItem.OnMenuItemClickListener;
73b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.OrientationEventListener;
74b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.SurfaceHolder;
75b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.View;
76b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.ViewGroup;
77b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.ViewGroup.LayoutParams;
78b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Window;
79b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.WindowManager;
80b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.AlphaAnimation;
81b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.Animation;
82b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.AnimationUtils;
83b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.ImageView;
84b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.Toast;
85b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
86b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpublic class Camera extends Activity implements View.OnClickListener,
87b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback {
88b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
89b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final String TAG = "camera";
90b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
91b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final boolean DEBUG = false;
92b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final boolean DEBUG_TIME_OPERATIONS = DEBUG && false;
93b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
94b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int CROP_MSG = 1;
95b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int RESTART_PREVIEW = 3;
96b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int CLEAR_SCREEN_DELAY = 4;
97b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
98b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int SCREEN_DELAY = 2 * 60 * 1000;
99b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int FOCUS_BEEP_VOLUME = 100;
100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SWITCH_TO_VIDEO = 0;
102b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SWITCH_TO_CAMERA = 1;
103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_FLASH_SETTING = 2;
104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_FLASH_AUTO = 3;
105b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_FLASH_ON = 4;
106b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_FLASH_OFF = 5;
107b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SETTINGS = 6;
108b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_PHOTOS = 7;
109b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_VIDEOS = 8;
110b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_SELECT_PHOTOS = 30;
111b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_NEW_PHOTO = 31;
112b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_GALLERY_PHOTO = 34;
113b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_GALLERY_VIDEO_PHOTO = 35;
114b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_CAMERA_DONE = 36;
115b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_CAMERA_VIDEO_DONE = 37;
116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private OrientationEventListener mOrientationListener;
118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mLastOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private SharedPreferences mPreferences;
120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int IDLE = 1;
122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int SNAPSHOT_IN_PROGRESS = 2;
123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int SNAPSHOT_COMPLETED = 3;
124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
125b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mStatus = IDLE;
126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final String sTempCropFilename = "crop-temp";
127b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
128b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private android.hardware.Camera mCameraDevice;
129b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private android.hardware.Camera.Parameters mParameters;
130b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private VideoPreview mSurfaceView;
131b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private SurfaceHolder mSurfaceHolder = null;
132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private View mBlackout = null;
133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
134b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mOriginalViewFinderWidth, mOriginalViewFinderHeight;
135b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mViewFinderWidth, mViewFinderHeight;
136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mPreviewing = false;
137b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private MediaPlayer mClickSound;
139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Capturer mCaptureObject;
141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ImageCapture mImageCapture = null;
142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mPausing = false;
144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1459c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUS_NOT_STARTED = 0;
1469c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUSING = 1;
1479c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUSING_SNAP_ON_FINISH = 2;
1489c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUS_SUCCESS = 3;
1499c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUS_FAIL = 4;
1509c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private int mFocusState = FOCUS_NOT_STARTED;
151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static ContentResolver mContentResolver;
153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mDidRegister = false;
154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ArrayList<MenuItem> mGalleryItems = new ArrayList<MenuItem>();
156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ImageView mLastPictureButton;
158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private LayerDrawable mVignette;
159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Animation mShowLastPictureButtonAnimation = new AlphaAnimation(0F, 1F);
160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mShouldShowLastPictureButton;
161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private TransitionDrawable mThumbnailTransition;
162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Drawable[] mThumbnails;
163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mShouldTransitionThumbnails;
164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Uri mLastPictureUri;
165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Bitmap mLastPictureThumb;
166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private LocationManager mLocationManager = null;
167b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
168b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ShutterButton mShutterButton;
169b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
170b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Animation mFocusBlinkAnimation;
171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private View mFocusIndicator;
172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ToneGenerator mFocusToneGenerator;
173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ShutterCallback mShutterCallback = new ShutterCallback();
176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private RawPictureCallback mRawPictureCallback = new RawPictureCallback();
177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private AutoFocusCallback mAutoFocusCallback = new AutoFocusCallback();
178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mFocusStartTime;
179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mFocusCallbackTime;
180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mCaptureStartTime;
181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mShutterCallbackTime;
182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mRawPictureCallbackTime;
183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mPicturesRemaining;
184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mKeepAndRestartPreview;
186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
187b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // mPostCaptureAlert is non-null only if isImageCaptureIntent() is true.
188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private View mPostCaptureAlert;
189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Handler mHandler = new MainHandler();
192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
193b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private interface Capturer {
194b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Uri getLastCaptureUri();
195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        void onSnap();
1969a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        void dismissFreezeFrame();
197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /** This Handler is used to post message back onto the main thread of the application */
200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class MainHandler extends Handler {
201b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void handleMessage(Message msg) {
203b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            switch (msg.what) {
204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case RESTART_PREVIEW: {
205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (mStatus == SNAPSHOT_IN_PROGRESS) {
206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // We are still in the processing of taking the picture, wait.
207b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // This is is strange.  Why are we polling?
208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // TODO remove polling
209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mHandler.sendEmptyMessageDelayed(RESTART_PREVIEW, 100);
210b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } else if (mStatus == SNAPSHOT_COMPLETED){
2119a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                        mCaptureObject.dismissFreezeFrame();
212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        hidePostCaptureAlert();
213b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
214b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
215b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
216b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
217b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case CLEAR_SCREEN_DELAY: {
218b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
219b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
220b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
221b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
222b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
223b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
225b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    LocationListener [] mLocationListeners = new LocationListener[] {
226b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            new LocationListener(LocationManager.GPS_PROVIDER),
227b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            new LocationListener(LocationManager.NETWORK_PROVIDER)
228b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
229b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
230b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
231b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
232b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
233b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onReceive(Context context, Intent intent) {
234b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            String action = intent.getAction();
235b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
236b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // SD card available
237b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                updateStorageHint(calculatePicturesRemaining());
238b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED) ||
239b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    action.equals(Intent.ACTION_MEDIA_CHECKING)) {
240b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // SD card unavailable
241b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mPicturesRemaining = MenuHelper.NO_STORAGE_ERROR;
242b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                updateStorageHint(mPicturesRemaining);
243b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) {
244b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Toast.makeText(Camera.this, getResources().getString(R.string.wait), 5000);
245b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) {
246b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                updateStorageHint();
247b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
248b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
249b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
250b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
251b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class LocationListener implements android.location.LocationListener {
252b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Location mLastLocation;
253b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean mValid = false;
254b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String mProvider;
255b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
256b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public LocationListener(String provider) {
257b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mProvider = provider;
258b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastLocation = new Location(mProvider);
259b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
260b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
261b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onLocationChanged(Location newLocation) {
262b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (newLocation.getLatitude() == 0.0 && newLocation.getLongitude() == 0.0) {
263b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // Hack to filter out 0.0,0.0 locations
264b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
265b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
266b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastLocation.set(newLocation);
267b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mValid = true;
268b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
269b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
270b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onProviderEnabled(String provider) {
271b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
272b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
273b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onProviderDisabled(String provider) {
274b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mValid = false;
275b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
276b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
277b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onStatusChanged(String provider, int status, Bundle extras) {
278b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (status == LocationProvider.OUT_OF_SERVICE) {
279b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mValid = false;
280b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
281b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
282b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
283b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public Location current() {
284b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return mValid ? mLastLocation : null;
285b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
286b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
287b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
288b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mImageSavingItem = false;
289b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
290b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final class ShutterCallback implements android.hardware.Camera.ShutterCallback {
291b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onShutter() {
292b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) {
293b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mShutterCallbackTime = System.currentTimeMillis();
294b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "Shutter lag was " + (mShutterCallbackTime - mCaptureStartTime) + " ms.");
295b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
296b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mClickSound != null) {
297b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mClickSound.start();
298b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mBlackout.setVisibility(View.VISIBLE);
300b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
301b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Size pictureSize = mParameters.getPictureSize();
302b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Resize the SurfaceView to the aspect-ratio of the still image
303b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // and so that we can see the full image that was taken.
304b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mSurfaceView.setAspectRatio(pictureSize.width, pictureSize.height);
305b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
306b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
307b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
308b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final class RawPictureCallback implements PictureCallback {
309b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onPictureTaken(byte [] rawData, android.hardware.Camera camera) {
310b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (Config.LOGV)
311b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "got RawPictureCallback...");
312b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRawPictureCallbackTime = System.currentTimeMillis();
313b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) {
314b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, (mRawPictureCallbackTime - mShutterCallbackTime) + "ms elapsed between" +
315b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        " ShutterCallback and RawPictureCallback.");
316b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
317b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mBlackout.setVisibility(View.GONE);
318b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
319b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
320b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
321b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final class JpegPictureCallback implements PictureCallback {
322b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Location mLocation;
323b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
324b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public JpegPictureCallback(Location loc) {
325b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLocation = loc;
326b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
327b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
328b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onPictureTaken(byte [] jpegData, android.hardware.Camera camera) {
329b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (Config.LOGV)
330b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "got JpegPictureCallback...");
331b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) {
333b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                long mJpegPictureCallback = System.currentTimeMillis();
334b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, (mJpegPictureCallback - mRawPictureCallbackTime) + "ms elapsed between" +
335b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        " RawPictureCallback and JpegPictureCallback.");
336b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
337b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
338b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mImageCapture.storeImage(jpegData, camera, mLocation);
339b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
340b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStatus = SNAPSHOT_COMPLETED;
341b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
342b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mKeepAndRestartPreview) {
343b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                long delay = 1500 - (System.currentTimeMillis() - mRawPictureCallbackTime);
344b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mHandler.sendEmptyMessageDelayed(RESTART_PREVIEW, Math.max(delay, 0));
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 AutoFocusCallback implements android.hardware.Camera.AutoFocusCallback {
350b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onAutoFocus(boolean focused, android.hardware.Camera camera) {
351b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) {
352b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mFocusCallbackTime = System.currentTimeMillis();
353b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "Auto focus took " + (mFocusCallbackTime - mFocusStartTime) + " ms.");
354b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
355b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3569c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            if (mFocusState == FOCUSING_SNAP_ON_FINISH && mCaptureObject != null) {
3579c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // Take the picture no matter focus succeeds or fails.
3589c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // No need to play the AF sound if we're about to play the shutter sound.
3599c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                mCaptureObject.onSnap();
3609c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                clearFocusState();
3619c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            } else if (mFocusState == FOCUSING) {
3629c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // User is half-pressing the focus key. Play the focus tone.
3639c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // Do not take the picture now.
3649c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                ToneGenerator tg = mFocusToneGenerator;
3659c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                if (tg != null)
3669c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                   tg.startTone(ToneGenerator.TONE_PROP_BEEP2);
3679c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                if (focused) {
3689c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusState = FOCUS_SUCCESS;
369b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
3709c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                else {
3719c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusState = FOCUS_FAIL;
3729c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                }
3739c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            } else if (mFocusState == FOCUS_NOT_STARTED) {
3749c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // User has released the focus key before focus completes.
3759c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // Do nothing.
3769c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            }
377b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateFocusIndicator();
378b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
379b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
380b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
381b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class ImageCapture implements Capturer {
382b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
383b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private boolean mCancel = false;
384b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private boolean mCapturing = false;
385b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
386b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private Uri mLastContentUri;
387b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private ImageManager.IAddImage_cancelable mAddImageCancelable;
388b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
389b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bitmap mCaptureOnlyBitmap;
390b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
391b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        /** These member variables are used for various debug timings */
392b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private long mThreadTimeStart;
393b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private long mThreadTimeEnd;
394b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private long mWallTimeStart;
395b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private long mWallTimeEnd;
396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
397b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
398b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public ImageCapture() {
399b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
400b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
401b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        /**
402b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         * This method sets whether or not we are capturing a picture. This method must be called
403b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         * with the ImageCapture.this lock held.
404b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         */
405b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void setCapturingLocked(boolean capturing) {
406b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCapturing = capturing;
407b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
408b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4099a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        public void dismissFreezeFrame() {
410b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStatus == SNAPSHOT_IN_PROGRESS) {
411b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // If we are still in the process of taking a picture, then just post a message.
412b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mHandler.sendEmptyMessage(RESTART_PREVIEW);
413b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
414b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                restartPreview();
415b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
416b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
417b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
418b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private void startTiming() {
419b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mWallTimeStart = SystemClock.elapsedRealtime();
420b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mThreadTimeStart = Debug.threadCpuTimeNanos();
421b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
422b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
423b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private void stopTiming() {
424b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mThreadTimeEnd = Debug.threadCpuTimeNanos();
425b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mWallTimeEnd = SystemClock.elapsedRealtime();
426b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
427b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
428b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private void storeImage(byte[] data, Location loc) {
429b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
430b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
431b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    startTiming();
432b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
433b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                long dateTaken = System.currentTimeMillis();
434b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                String name = createName(dateTaken) + ".jpg";
435b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mLastContentUri = ImageManager.instance().addImage(
436b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        Camera.this,
437b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mContentResolver,
438b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        name,
439b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        "",
440b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        dateTaken,
441b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // location for the database goes here
442b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        loc,
443b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        0,   // the dsp will use the right orientation so don't "double set it"
444b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        ImageManager.CAMERA_IMAGE_BUCKET_NAME,
445b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        name);
446b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
447b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mLastContentUri == null) {
448b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // this means we got an error
449b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCancel = true;
450b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (!mCancel) {
452b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mAddImageCancelable = ImageManager.instance().storeImage(mLastContentUri,
453b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            Camera.this, mContentResolver, 0, null, data);
454b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mAddImageCancelable.get();
455b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mAddImageCancelable = null;
456b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
457b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
458b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
459b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    stopTiming();
460b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.d(TAG, "Storing image took " + (mWallTimeEnd - mWallTimeStart) + " ms. " +
461b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            "Thread time was " + ((mThreadTimeEnd - mThreadTimeStart) / 1000000) +
462b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            " ms.");
463b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
464b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (Exception ex) {
465b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Exception while compressing image.", ex);
466b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
467b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
468b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
469b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void storeImage(byte[] data, android.hardware.Camera camera, Location loc) {
470b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            boolean captureOnly = isImageCaptureIntent();
471b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
472b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (!captureOnly) {
473b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                storeImage(data, loc);
474b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                sendBroadcast(new Intent("com.android.camera.NEW_PICTURE", mLastContentUri));
475b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setLastPictureThumb(data, mCaptureObject.getLastCaptureUri());
4769a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                dismissFreezeFrame();
477b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
478b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                BitmapFactory.Options options = new BitmapFactory.Options();
479b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                options.inSampleSize = 4;
480b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
481b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
482b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    startTiming();
483b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
484b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
485b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCaptureOnlyBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
486b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
487b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
488b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    stopTiming();
489b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.d(TAG, "Decoded mCaptureOnly bitmap (" + mCaptureOnlyBitmap.getWidth() +
490b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            "x" + mCaptureOnlyBitmap.getHeight() + " ) in " +
491b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            (mWallTimeEnd - mWallTimeStart) + " ms. Thread time was " +
492b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            ((mThreadTimeEnd - mThreadTimeStart) / 1000000) + " ms.");
493b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
494b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
495b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                showPostCaptureAlert();
496b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                cancelAutomaticPreviewRestart();
497b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
498b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
499b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCapturing = false;
500b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mPausing) {
501b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                closeCamera();
502b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
503b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
504b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
505b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        /*
506b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         * Initiate the capture of an image.
507b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         */
508b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void initiate(boolean captureOnly) {
509b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCameraDevice == null) {
510b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
511b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
512b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
513b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCancel = false;
514b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCapturing = true;
515b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
516b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            capture(captureOnly);
517b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
518b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
519b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public Uri getLastCaptureUri() {
520b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return mLastContentUri;
521b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
522b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
523b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public Bitmap getLastBitmap() {
524b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return mCaptureOnlyBitmap;
525b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
526b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
527b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private void capture(boolean captureOnly) {
528b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPreviewing = false;
529b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCaptureOnlyBitmap = null;
530b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
531b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            final int latchedOrientation = ImageManager.roundOrientation(mLastOrientation + 90);
532b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
533b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Boolean recordLocation = mPreferences.getBoolean("pref_camera_recordlocation_key", false);
534b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Location loc = recordLocation ? getCurrentLocation() : null;
535b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Quality 75 has visible artifacts, and quality 90 looks great but the files begin to
536b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // get large. 85 is a good compromise between the two.
537b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParameters.set("jpeg-quality", 85);
538b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParameters.set("rotation", latchedOrientation);
539b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
540b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParameters.remove("gps-latitude");
541b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParameters.remove("gps-longitude");
542b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParameters.remove("gps-altitude");
543b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParameters.remove("gps-timestamp");
544b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
545b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (loc != null) {
546b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                double lat = loc.getLatitude();
547b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                double lon = loc.getLongitude();
548b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                boolean hasLatLon = (lat != 0.0d) || (lon != 0.0d);
549b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
550b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (hasLatLon) {
551b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    String latString = String.valueOf(lat);
552b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    String lonString = String.valueOf(lon);
553b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mParameters.set("gps-latitude",  latString);
554b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mParameters.set("gps-longitude", lonString);
555d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                    if (loc.hasAltitude()) {
556b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mParameters.set("gps-altitude",  String.valueOf(loc.getAltitude()));
557d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                    } else {
558d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                        // for NETWORK_PROVIDER location provider, we may have
559d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                        // no altitude information, but the driver needs it, so
560d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                        // we fake one.
561d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                        mParameters.set("gps-altitude",  "0");
562d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                    }
563b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (loc.getTime() != 0) {
564b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // Location.getTime() is UTC in milliseconds.
565b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // gps-timestamp is UTC in seconds.
566b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        long utcTimeSeconds = loc.getTime() / 1000;
567b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mParameters.set("gps-timestamp", String.valueOf(utcTimeSeconds));
568b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
569b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } else {
570b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    loc = null;
571b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
572b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
573b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
574b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.setParameters(mParameters);
575b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
576b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback, new JpegPictureCallback(loc));
577b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Prepare the sound to play in shutter callback.
578b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mClickSound != null) {
579b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mClickSound.seekTo(0);
580b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
581b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
582b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
583b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onSnap() {
584b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) mCaptureStartTime = System.currentTimeMillis();
585b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // If we are already in the middle of taking a snapshot then we should just save
587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // the image after we have returned from the camera service.
588b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStatus == SNAPSHOT_IN_PROGRESS || mStatus == SNAPSHOT_COMPLETED) {
589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mKeepAndRestartPreview = true;
590b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mHandler.sendEmptyMessage(RESTART_PREVIEW);
591b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
592b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
593b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
594b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Don't check the filesystem here, we can't afford the latency. Instead, check the
595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // cached value which was calculated when the preview was restarted.
596b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mPicturesRemaining < 1) {
597b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                updateStorageHint(mPicturesRemaining);
598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
600b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStatus = SNAPSHOT_IN_PROGRESS;
602b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
603b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mKeepAndRestartPreview = true;
604b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
605b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            boolean getContentAction = isImageCaptureIntent();
606b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (getContentAction) {
607b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mImageCapture.initiate(true);
608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
609b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mImageCapture.initiate(false);
610b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
611b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
6129a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
6139a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        private void clearLastBitmap() {
6149a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            if (mCaptureOnlyBitmap != null) {
6159a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                mCaptureOnlyBitmap.recycle();
6169a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                mCaptureOnlyBitmap = null;
6179a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            }
6189a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
619b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
620b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
621b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setLastPictureThumb(byte[] data, Uri uri) {
622b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        BitmapFactory.Options options = new BitmapFactory.Options();
623b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        options.inSampleSize = 16;
624b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
625b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bitmap lastPictureThumb = BitmapFactory.decodeByteArray(data, 0, data.length, options);
626b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setLastPictureThumb(lastPictureThumb, uri);
628b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
629b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
630b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setLastPictureThumb(Bitmap lastPictureThumb, Uri uri) {
631b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
632b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        final int PADDING_WIDTH = 2;
633b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        final int PADDING_HEIGHT = 2;
634b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        LayoutParams layoutParams = mLastPictureButton.getLayoutParams();
635b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // Make the mini-thumbnail size smaller than the button size so that the image corners
636b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // don't peek out from the rounded corners of the frame_thumbnail graphic:
637b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        final int miniThumbWidth = layoutParams.width - 2 * PADDING_WIDTH;
638b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        final int miniThumbHeight = layoutParams.height - 2 * PADDING_HEIGHT;
639b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
640b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        lastPictureThumb = ImageManager.extractMiniThumb(lastPictureThumb,
641b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                miniThumbWidth, miniThumbHeight);
642b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
643b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Drawable[] vignetteLayers = new Drawable[2];
644b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        vignetteLayers[1] = getResources().getDrawable(R.drawable.frame_thumbnail);
645b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mThumbnails == null) {
646b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mThumbnails = new Drawable[2];
647b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mThumbnails[1] = new BitmapDrawable(lastPictureThumb);
648b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            vignetteLayers[0] = mThumbnails[1];
649b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
650b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mThumbnails[0] = mThumbnails[1];
651b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mThumbnails[1] = new BitmapDrawable(lastPictureThumb);
652b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mThumbnailTransition = new TransitionDrawable(mThumbnails);
653b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mShouldTransitionThumbnails = true;
654b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            vignetteLayers[0] = mThumbnailTransition;
655b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
656b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
657b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVignette = new LayerDrawable(vignetteLayers);
658b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVignette.setLayerInset(0, PADDING_WIDTH, PADDING_HEIGHT,
659b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                PADDING_WIDTH, PADDING_HEIGHT);
660b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mLastPictureButton.setImageDrawable(mVignette);
661b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
662b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mLastPictureButton.getVisibility() != View.VISIBLE) {
663b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mShouldShowLastPictureButton = true;
664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
665b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mLastPictureThumb = lastPictureThumb;
666b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mLastPictureUri = uri;
667b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
668b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    static private String createName(long dateTaken) {
670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString();
671b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
672b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
673b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    static public Matrix GetDisplayMatrix(Bitmap b, ImageView v) {
674b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Matrix m = new Matrix();
675b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        float bw = (float)b.getWidth();
676b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        float bh = (float)b.getHeight();
677b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        float vw = (float)v.getWidth();
678b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        float vh = (float)v.getHeight();
679b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        float scale, x, y;
680b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (bw*vh > vw*bh) {
681b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            scale = vh / bh;
682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            x = (vw - scale*bw)*0.5F;
683b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            y = 0;
684b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
685b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            scale = vw / bw;
686b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            x = 0;
687b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            y = (vh - scale*bh)*0.5F;
688b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
689b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        m.setScale(scale, scale, 0.5F, 0.5F);
690b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        m.postTranslate(x, y);
691b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return m;
692b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
693b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
694b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /** Called with the activity is first created. */
695b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
696b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onCreate(Bundle icicle) {
697b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreate(icicle);
698b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
699b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // To reduce startup time, we open camera device in another thread.
700b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // We make sure the camera is opened at the end of onCreate.
701b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Thread openCameraThread = new Thread(new Runnable() {
702b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public void run() {
703b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCameraDevice = android.hardware.Camera.open();
704b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
705b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
706b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        openCameraThread.start();
707b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
708b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // To reduce startup time, we run some service creation code in another thread.
709b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // We make sure the services are loaded at the end of onCreate().
710b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Thread loadServiceThread = new Thread(new Runnable() {
711b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public void run() {
712b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
713b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mOrientationListener = new OrientationEventListener(Camera.this) {
714b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    public void onOrientationChanged(int orientation) {
7159c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                        // We keep the last known orientation. So if the user
7169c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                        // first orient the camera then point the camera to
7179c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                        // floor/sky, we still have the correct orientation.
7189c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                        if (orientation != ORIENTATION_UNKNOWN)
7199c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                            mLastOrientation = orientation;
720b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
721b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                };
722b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
723b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
724b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        loadServiceThread.start();
725b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
726b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
727b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mContentResolver = getContentResolver();
728b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
729b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window win = getWindow();
730b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
731b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setContentView(R.layout.camera);
732b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
733b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceView = (VideoPreview) findViewById(R.id.camera_preview);
734b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
735b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // don't set mSurfaceHolder here. We have it set ONLY within
736b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // surfaceCreated / surfaceDestroyed, other parts of the code
737b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // assume that when it is set, the surface is also set.
738b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SurfaceHolder holder = mSurfaceView.getHolder();
739b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.addCallback(this);
740b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
741b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
742b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mBlackout = findViewById(R.id.blackout);
743b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
744b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (!isImageCaptureIntent())  {
745b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastPictureButton = (ImageView) findViewById(R.id.last_picture_button);
746b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastPictureButton.setOnClickListener(this);
747b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            loadLastThumb();
748b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
749b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
750b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton = (ShutterButton) findViewById(R.id.shutter_button);
751b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setOnShutterButtonListener(this);
752b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
753b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
754b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mClickSound = new MediaPlayer();
755b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.camera_click);
756b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
757b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mClickSound.setDataSource(afd.getFileDescriptor(),
758b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                             afd.getStartOffset(),
759b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                             afd.getLength());
760b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
761b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mClickSound != null) {
762b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mClickSound.setAudioStreamType(AudioManager.STREAM_ALARM);
763b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mClickSound.prepare();
764b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
765b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (Exception ex) {
766b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.w(TAG, "Couldn't create click sound", ex);
767b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
768b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
769b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mFocusIndicator = findViewById(R.id.focus_indicator);
770b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mFocusBlinkAnimation = AnimationUtils.loadAnimation(this, R.anim.auto_focus_blink);
771b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mFocusBlinkAnimation.setRepeatCount(Animation.INFINITE);
772b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mFocusBlinkAnimation.setRepeatMode(Animation.REVERSE);
773b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
774b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // We load the post_picture_panel layout only if it is needed.
775b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (isImageCaptureIntent()) {
776b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ViewGroup cameraView = (ViewGroup)findViewById(R.id.camera);
777b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            getLayoutInflater().inflate(R.layout.post_picture_panel,
778b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                                        cameraView);
779b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostCaptureAlert = findViewById(R.id.post_picture_panel);
780b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
781b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
782b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // Make sure the services are loaded.
783b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
784b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            openCameraThread.join();
785b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            loadServiceThread.join();
786b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (InterruptedException ex) {
787b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
788b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
789b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ImageManager.ensureOSXCompatibleFolder();
790b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
791b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
792b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
793b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onStart() {
794b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onStart();
795b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
796b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Thread t = new Thread(new Runnable() {
797b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public void run() {
798b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                final boolean storageOK = calculatePicturesRemaining() > 0;
799b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
800b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (!storageOK) {
801b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mHandler.post(new Runnable() {
802b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run() {
803b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            updateStorageHint(mPicturesRemaining);
804b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
805b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    });
806b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
807b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
808b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
809b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        t.start();
810b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
811b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
812b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onClick(View v) {
813b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (v.getId()) {
814b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case R.id.last_picture_button:
815b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            viewLastImage();
816b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            break;
817b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case R.id.attach:
818b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            doAttach();
819b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            break;
820b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case R.id.cancel:
821b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            doCancel();
822b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
823b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
824b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
825b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doAttach() {
826b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bitmap bitmap = mImageCapture.getLastBitmap();
827b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
828b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String cropValue = null;
829b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Uri saveUri = null;
830b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
831b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bundle myExtras = getIntent().getExtras();
832b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (myExtras != null) {
833b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
834b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cropValue = myExtras.getString("crop");
835b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
836b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
837b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
838b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (cropValue == null) {
839b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            /*
840b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project             * First handle the no crop case -- just return the value.  If the caller
841b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project             * specifies a "save uri" then write the data to it's stream.  Otherwise,
842b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project             * pass back a scaled down version of the bitmap directly in the extras.
843b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project             */
844b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (saveUri != null) {
845b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                OutputStream outputStream = null;
846b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
847b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    outputStream = mContentResolver.openOutputStream(saveUri);
848b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    bitmap.compress(Bitmap.CompressFormat.JPEG, 75, outputStream);
849b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    outputStream.close();
850b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
851b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    setResult(RESULT_OK);
852b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    finish();
853b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } catch (IOException ex) {
854b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    //
855b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } finally {
856b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (outputStream != null) {
857b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        try {
858b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            outputStream.close();
859b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        } catch (IOException ex) {
860b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
861b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
862b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
863b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
864b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
865b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                float scale = .5F;
866b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Matrix m = new Matrix();
867b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                m.setScale(scale, scale);
868b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
869b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                bitmap = Bitmap.createBitmap(bitmap, 0, 0,
870b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        bitmap.getWidth(),
871b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        bitmap.getHeight(),
872b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        m, true);
873b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
874b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setResult(RESULT_OK, new Intent("inline-data").putExtra("data", bitmap));
875b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                finish();
876b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
877b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
878b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        else {
879b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            /*
880b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project             * Save the image to a temp file and invoke the cropper
881b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project             */
882b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri tempUri = null;
883b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            FileOutputStream tempStream = null;
884b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
885b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                File path = getFileStreamPath(sTempCropFilename);
886b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                path.delete();
887b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                tempStream = openFileOutput(sTempCropFilename, 0);
888b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                bitmap.compress(Bitmap.CompressFormat.JPEG, 75, tempStream);
889b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                tempStream.close();
890b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                tempUri = Uri.fromFile(path);
891b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (FileNotFoundException ex) {
892b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setResult(Activity.RESULT_CANCELED);
893b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                finish();
894b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
895b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (IOException ex) {
896b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setResult(Activity.RESULT_CANCELED);
897b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                finish();
898b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
899b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } finally {
900b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (tempStream != null) {
901b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    try {
902b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        tempStream.close();
903b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } catch (IOException ex) {
904b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
905b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
906b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
907b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
908b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
909b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Bundle newExtras = new Bundle();
910b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (cropValue.equals("circle"))
911b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                newExtras.putString("circleCrop", "true");
912b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (saveUri != null)
913b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, saveUri);
914b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            else
915b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                newExtras.putBoolean("return-data", true);
916b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
917b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Intent cropIntent = new Intent();
918b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cropIntent.setClass(Camera.this, CropImage.class);
919b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cropIntent.setData(tempUri);
920b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cropIntent.putExtras(newExtras);
921b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
922b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            startActivityForResult(cropIntent, CROP_MSG);
923b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
924b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
925b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
926b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doCancel() {
927b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setResult(RESULT_CANCELED, new Intent());
928b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        finish();
929b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
930b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
931b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onShutterButtonFocus(ShutterButton button, boolean pressed) {
932b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (button.getId()) {
933b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.shutter_button:
934b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doFocus(pressed);
935b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
936b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
937b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
938b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
939b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onShutterButtonClick(ShutterButton button) {
940b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (button.getId()) {
941b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.shutter_button:
9429c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                doSnap();
943b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
944b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
945b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
946b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
947b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateStorageHint() {
948b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project      updateStorageHint(MenuHelper.calculatePicturesRemaining());
949b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
950b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
951b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private OnScreenHint mStorageHint;
952b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
953b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateStorageHint(int remaining) {
954b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String noStorageText = null;
955b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
956b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (remaining == MenuHelper.NO_STORAGE_ERROR) {
957b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            String state = Environment.getExternalStorageState();
958b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (state == Environment.MEDIA_CHECKING) {
959b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                noStorageText = getString(R.string.preparing_sd);
960b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
961b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                noStorageText = getString(R.string.no_storage);
962b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
963b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else if (remaining < 1) {
964b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            noStorageText = getString(R.string.not_enough_space);
965b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
966b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
967b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (noStorageText != null) {
968b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStorageHint == null) {
969b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint = OnScreenHint.makeText(this, noStorageText);
970b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
971b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint.setText(noStorageText);
972b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
973b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.show();
974b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else if (mStorageHint != null) {
975b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
976b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
977b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
978b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
979b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
980b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
981b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onResume() {
982b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onResume();
983b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
984b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
985b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPausing = false;
986b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mOrientationListener.enable();
987b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
988b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // install an intent filter to receive SD card related events.
989b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
990b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
991b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
992b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
993b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_CHECKING);
994b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addDataScheme("file");
995b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        registerReceiver(mReceiver, intentFilter);
996b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mDidRegister = true;
997b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
998b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mImageCapture = new ImageCapture();
999b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1000b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        restartPreview();
1001b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1002b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mPreferences.getBoolean("pref_camera_recordlocation_key", false))
1003b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            startReceivingLocationUpdates();
1004b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1005b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        updateFocusIndicator();
1006b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1007b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
1008b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mFocusToneGenerator = new ToneGenerator(AudioManager.STREAM_SYSTEM, FOCUS_BEEP_VOLUME);
1009b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (RuntimeException e) {
1010b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.w(TAG, "Exception caught while creating local tone generator: " + e);
1011b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mFocusToneGenerator = null;
1012b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1013b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1014b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mBlackout.setVisibility(View.GONE);
1015b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1016b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1017b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ImageManager.DataLocation dataLocation() {
1018b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return ImageManager.DataLocation.EXTERNAL;
1019b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1020b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1021b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int BUFSIZE = 4096;
1022b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1023b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // Stores the thumbnail and URI of last-picture-taken to SD card, so we can
1024b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // load it the next time the Camera app starts.
1025b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void storeLastThumb() {
1026b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mLastPictureUri != null && mLastPictureThumb != null) {
1027b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1028b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                FileOutputStream f = new FileOutputStream(ImageManager.getLastThumbPath());
1029b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
1030b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    BufferedOutputStream b = new BufferedOutputStream(f, BUFSIZE);
1031b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    try {
1032b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        DataOutputStream d = new DataOutputStream(b);
1033b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        try {
1034b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            d.writeUTF(mLastPictureUri.toString());
1035b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            mLastPictureThumb.compress(Bitmap.CompressFormat.PNG, 100, d);
1036b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        } finally {
1037b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            d.close();
1038b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            b = null;
1039b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            f = null;
1040b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
1041b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } finally {
1042b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        if (b != null) {
1043b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            b.close();
1044b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            f = null;
1045b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
1046b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
1047b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } finally {
1048b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (f != null) {
1049b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        f.close();
1050b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
1051b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1052b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (IOException e) {
1053b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1054b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1055b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1056b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1057b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // Loads the thumbnail and URI of last-picture-taken from SD card.
1058b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void loadLastThumb() {
1059b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
1060b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            FileInputStream f = new FileInputStream(ImageManager.getLastThumbPath());
1061b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1062b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                BufferedInputStream b = new BufferedInputStream(f, BUFSIZE);
1063b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
1064b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    DataInputStream d = new DataInputStream(b);
1065b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    try {
1066b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        Uri lastUri = Uri.parse(d.readUTF());
1067b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        Bitmap lastThumb = BitmapFactory.decodeStream(d);
1068b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        setLastPictureThumb(lastThumb, lastUri);
1069b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } finally {
1070b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        d.close();
1071b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        b = null;
1072b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        f = null;
1073b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
1074b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } finally {
1075b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (b != null) {
1076b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        b.close();
1077b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        f = null;
1078b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
1079b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1080b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } finally {
1081b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (f != null) {
1082b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    f.close();
1083b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1084b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1085b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (IOException e) {
1086b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1087b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1088b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1089b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1090b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onStop() {
1091b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        keep();
1092b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopPreview();
1093b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        closeCamera();
1094b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1095b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onStop();
1096b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1097b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1098b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1099b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    protected void onPause() {
1100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        keep();
1101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1102b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPausing = true;
1103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mOrientationListener.disable();
1104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1105b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopPreview();
1106b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1107b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (!mImageCapture.mCapturing) {
1108b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            closeCamera();
1109b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1110b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mDidRegister) {
1111b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            unregisterReceiver(mReceiver);
1112b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mDidRegister = false;
1113b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1114b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopReceivingLocationUpdates();
1115b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mFocusToneGenerator != null) {
1117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mFocusToneGenerator.release();
1118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mFocusToneGenerator = null;
1119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        storeLastThumb();
1122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mStorageHint != null) {
1123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
1124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
1125b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
11269a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
11279a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        // If we are in an image capture intent and has taken
11289a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        // a picture, we just clear it in onPause.
11299a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mImageCapture.clearLastBitmap();
11309a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mImageCapture = null;
11319a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        hidePostCaptureAlert();
11329a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
1133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPause();
1134b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1135b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1137b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
1138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (requestCode) {
1139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case CROP_MSG: {
1140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Intent intent = new Intent();
1141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (data != null) {
1142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Bundle extras = data.getExtras();
1143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (extras != null) {
1144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        intent.putExtras(extras);
1145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
1146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1147b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setResult(resultCode, intent);
1148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                finish();
1149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1150b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                File path = getFileStreamPath(sTempCropFilename);
1151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                path.delete();
1152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
1154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void autoFocus() {
1159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        updateFocusIndicator();
11609c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        if (mFocusState != FOCUSING && mFocusState != FOCUSING_SNAP_ON_FINISH) {
1161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCameraDevice != null) {
1162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
1163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mFocusStartTime = System.currentTimeMillis();
1164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
11659c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                mFocusState = FOCUSING;
11669c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                mCameraDevice.autoFocus(mAutoFocusCallback);
1167b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1168b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1169b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1170b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11719c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private void clearFocusState() {
11729c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        mFocusState = FOCUS_NOT_STARTED;
1173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateFocusIndicator() {
1176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.post(new Runnable() {
1177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public void run() {
11789c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                if (mFocusState == FOCUS_SUCCESS) {
11799c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.setVisibility(View.VISIBLE);
1180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mFocusIndicator.clearAnimation();
11819c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                } else if (mFocusState == FOCUS_FAIL) {
11829c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.setVisibility(View.VISIBLE);
11839c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.startAnimation(mFocusBlinkAnimation);
1184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } else {
11859c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.setVisibility(View.GONE);
11869c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.clearAnimation();
1187b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
1190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1193b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1194b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
1195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
1196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
1197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (keyCode) {
1199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_BACK:
1200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mStatus == SNAPSHOT_IN_PROGRESS) {
1201b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // ignore backs while we're taking a picture
1202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
1203b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
1205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_FOCUS:
1206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
1207b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    doFocus(true);
1208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1210b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_CAMERA:
1211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
12129c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    doSnap();
1213b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1214b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1215b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_CENTER:
1216b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // If we get a dpad center event without any focused view, move the
1217b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // focus to the shutter button and press it.
1218b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
1219b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // Start auto-focus immediately to reduce shutter lag. After the shutter button
1220b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // gets the focus, doFocus() will be called again but it is fine.
1221b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    doFocus(true);
1222b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (mShutterButton.isInTouchMode()) {
1223b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mShutterButton.requestFocusFromTouch();
1224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } else {
1225b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mShutterButton.requestFocus();
1226b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
1227b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mShutterButton.setPressed(true);
1228b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1229b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1230b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1231b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1232b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyDown(keyCode, event);
1233b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1234b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1235b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1236b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
1237b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (keyCode) {
1238b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_FOCUS:
1239b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doFocus(false);
1240b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1241b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1242b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyUp(keyCode, event);
1243b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1244b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12459c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private void doSnap() {
12469c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // If the user has half-pressed the shutter and focus is completed, we
12479c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // can take the photo right away.
12489c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        if ((mFocusState == FOCUS_SUCCESS || mFocusState == FOCUS_FAIL)
12499c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                || !mPreviewing) {
1250b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // doesn't get set until the idler runs
1251b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCaptureObject != null) {
1252b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCaptureObject.onSnap();
1253b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
12549c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            clearFocusState();
1255b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateFocusIndicator();
1256b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
12579c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            // Half pressing the shutter (i.e. the focus button event) will
12589c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            // already have requested AF for us, so just request capture on
12599c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            // focus here.
12609c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            mFocusState = FOCUSING_SNAP_ON_FINISH;
1261b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1262b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1263b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1264b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doFocus(boolean pressed) {
12659c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        if (pressed) {  // Focus key down.
1266b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mPreviewing) {
1267b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                autoFocus();
1268b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (mCaptureObject != null) {
1269b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // Save and restart preview
1270b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCaptureObject.onSnap();
1271b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
12729c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        } else {  // Focus key up.
12739c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            if (mFocusState != FOCUSING_SNAP_ON_FINISH) {
12749c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // User releases half-pressed focus key.
12759c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                clearFocusState();
12769c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                updateFocusIndicator();
12779c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            }
1278b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1279b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1280b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1281b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
1282b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // if we're creating the surface, start the preview as well.
1283b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean preview = holder.isCreating();
1284b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setViewFinder(w, h, preview);
1285b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCaptureObject = mImageCapture;
1286b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1287b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1288b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceCreated(SurfaceHolder holder) {
1289b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = holder;
1290b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1291b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1292b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceDestroyed(SurfaceHolder holder) {
1293b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopPreview();
1294b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = null;
1295b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1296b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1297b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void closeCamera() {
1298b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraDevice != null) {
1299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.release();
1300b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice = null;
1301b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPreviewing = false;
1302b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1303b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1304b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1305b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean ensureCameraDevice() {
1306b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraDevice == null) {
1307b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice = android.hardware.Camera.open();
1308b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1309b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return mCameraDevice != null;
1310b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1311b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1312b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean isLastPictureValid() {
1313b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean isValid = true;
1314b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mLastPictureUri == null)  return false;
1315b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
1316b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mContentResolver.openFileDescriptor(mLastPictureUri, "r").close();
1317b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1318b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        catch (Exception ex) {
1319b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            isValid = false;
1320b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, ex.toString());
1321b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1322b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return isValid;
1323b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1324b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1325b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateLastImage() {
1326b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ImageManager.IImageList list = ImageManager.instance().allImages(
1327b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            this,
1328b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mContentResolver,
1329b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            dataLocation(),
1330b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ImageManager.INCLUDE_IMAGES,
1331b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ImageManager.SORT_ASCENDING,
1332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ImageManager.CAMERA_IMAGE_BUCKET_ID);
1333b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int count = list.getCount();
1334b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (count > 0) {
1335b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ImageManager.IImage image = list.getImageAt(count-1);
1336b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastPictureUri = image.fullSizeImageUri();
1337b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "updateLastImage: count="+ count +
1338b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                ", lastPictureUri="+mLastPictureUri);
1339b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setLastPictureThumb(image.miniThumbBitmap(), mLastPictureUri);
1340b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
1341b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastPictureUri = null;
1342b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1343b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        list.deactivate();
1344b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1345b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1346b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void restartPreview() {
1347b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        VideoPreview surfaceView = mSurfaceView;
1348b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1349b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // make sure the surfaceview fills the whole screen when previewing
1350b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        surfaceView.setAspectRatio(VideoPreview.DONT_CARE);
1351b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setViewFinder(mOriginalViewFinderWidth, mOriginalViewFinderHeight, true);
1352b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mStatus = IDLE;
1353b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1354b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // Calculate this in advance of each shot so we don't add to shutter latency. It's true that
1355b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // someone else could write to the SD card in the mean time and fill it, but that could have
1356b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // happened between the shutter press and saving the JPEG too.
1357b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // TODO: The best longterm solution is to write a reserve file of maximum JPEG size, always
1358b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // let the user take a picture, and delete that file if needed to save the new photo.
1359b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        calculatePicturesRemaining();
1360b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
13619c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        if (!isImageCaptureIntent() && !isLastPictureValid()) {
1362b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateLastImage();
1363b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1364b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1365b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mShouldShowLastPictureButton) {
1366b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mShouldShowLastPictureButton = false;
1367b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastPictureButton.setVisibility(View.VISIBLE);
1368b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Animation a = mShowLastPictureButtonAnimation;
1369b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            a.setDuration(500);
1370b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastPictureButton.setAnimation(a);
1371b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1372b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1373b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mShouldTransitionThumbnails) {
1374b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mShouldTransitionThumbnails = false;
1375b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mThumbnailTransition.startTransition(500);
1376b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1377b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1378b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1379b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setViewFinder(int w, int h, boolean startPreview) {
1380b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mPausing)
1381b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1382b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1383b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mPreviewing &&
1384b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                w == mViewFinderWidth &&
1385b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                h == mViewFinderHeight) {
1386b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1387b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1388b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1389b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (!ensureCameraDevice())
1390b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1391b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1392b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mSurfaceHolder == null)
1393b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1394b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1395b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (isFinishing())
1396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1397b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1398b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mPausing)
1399b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1400b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1401b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // remember view finder size
1402b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mViewFinderWidth = w;
1403b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mViewFinderHeight = h;
1404b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mOriginalViewFinderHeight == 0) {
1405b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mOriginalViewFinderWidth = w;
1406b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mOriginalViewFinderHeight = h;
1407b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1408b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1409b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (startPreview == false)
1410b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1411b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1412b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        /*
1413b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         * start the preview if we're asked to...
1414b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         */
1415b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1416b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // we want to start the preview and we're previewing already,
1417b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // stop the preview first (this will blank the screen).
1418b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mPreviewing)
1419b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            stopPreview();
1420b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1421b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // this blanks the screen if the surface changed, no-op otherwise
1422b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
1423b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.setPreviewDisplay(mSurfaceHolder);
1424b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (IOException exception) {
1425b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.release();
1426b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice = null;
1427b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // TODO: add more exception handling logic here
1428b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1429b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1430b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1431b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // request the preview size, the hardware may not honor it,
1432b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // if we depended on it we would have to query the size again
1433b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParameters = mCameraDevice.getParameters();
1434b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParameters.setPreviewSize(w, h);
1435b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
1436b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.setParameters(mParameters);
1437b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (IllegalArgumentException e) {
1438b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Ignore this error, it happens in the simulator.
1439b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1440b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1441b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1442b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        final long wallTimeStart = SystemClock.elapsedRealtime();
1443b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        final long threadTimeStart = Debug.threadCpuTimeNanos();
1444b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1445b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        final Object watchDogSync = new Object();
1446b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Thread watchDog = new Thread(new Runnable() {
1447b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public void run() {
1448b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                int next_warning = 1;
1449b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                while (true) {
1450b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    try {
1451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        synchronized (watchDogSync) {
1452b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            watchDogSync.wait(1000);
1453b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
1454b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } catch (InterruptedException ex) {
1455b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        //
1456b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
1457b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (mPreviewing)
1458b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        break;
1459b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1460b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    int delay = (int) (SystemClock.elapsedRealtime() - wallTimeStart) / 1000;
1461b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (delay >= next_warning) {
1462b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        if (delay < 120) {
1463b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            Log.e(TAG, "preview hasn't started yet in " + delay + " seconds");
1464b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        } else {
1465b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            Log.e(TAG, "preview hasn't started yet in " + (delay / 60) + " minutes");
1466b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
1467b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        if (next_warning < 60) {
1468b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            next_warning <<= 1;
1469b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            if (next_warning == 16) {
1470b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                                next_warning = 15;
1471b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            }
1472b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        } else {
1473b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            next_warning += 60;
1474b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
1475b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
1476b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1477b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1478b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
1479b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1480b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        watchDog.start();
1481b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1482b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (Config.LOGV)
1483b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "calling mCameraDevice.startPreview");
1484b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
1485b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.startPreview();
1486b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (Throwable e) {
1487b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // TODO: change Throwable to IOException once android.hardware.Camera.startPreview
1488b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // properly declares that it throws IOException.
1489b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1490b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPreviewing = true;
1491b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1492b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        synchronized (watchDogSync) {
1493b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            watchDogSync.notify();
1494b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1495b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1496b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        long threadTimeEnd = Debug.threadCpuTimeNanos();
1497b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        long wallTimeEnd = SystemClock.elapsedRealtime();
1498b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if ((wallTimeEnd - wallTimeStart) > 3000) {
1499b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.w(TAG, "startPreview() to " + (wallTimeEnd - wallTimeStart) + " ms. Thread time was"
1500b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    + (threadTimeEnd - threadTimeStart) / 1000000 + " ms.");
1501b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1502b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1503b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1504b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void stopPreview() {
1505b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraDevice != null && mPreviewing) {
1506b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.stopPreview();
1507b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1508b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPreviewing = false;
1509b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1510b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1511b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    void gotoGallery() {
1512b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.gotoCameraImageGallery(this);
1513b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1514b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1515b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void viewLastImage() {
1516b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Uri targetUri = mLastPictureUri;
1517b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (targetUri != null && isLastPictureValid()) {
1518b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            targetUri = targetUri.buildUpon().
1519b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                appendQueryParameter("bucketId", ImageManager.CAMERA_IMAGE_BUCKET_ID).build();
1520b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Intent intent = new Intent(Intent.ACTION_VIEW, targetUri);
1521b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            intent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION,
1522b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
1523b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            intent.putExtra(MediaStore.EXTRA_FULL_SCREEN, true);
1524b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            intent.putExtra(MediaStore.EXTRA_SHOW_ACTION_ICONS, true);
1525b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            intent.putExtra("com.android.camera.ReviewMode", true);
1526b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1527b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1528b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                startActivity(intent);
1529b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (android.content.ActivityNotFoundException ex) {
1530b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // ignore.
1531b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1532b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
1533b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "Can't view last image.");
1534b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1535b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1536b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1537b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    void keep() {
1538b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCaptureObject != null) {
15399a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            mCaptureObject.dismissFreezeFrame();
1540b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1541b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
1542b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1543b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ImageManager.IImage getImageForURI(Uri uri) {
1544b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ImageManager.IImageList list = ImageManager.instance().allImages(
1545b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                this,
1546b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mContentResolver,
1547b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                dataLocation(),
1548b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                ImageManager.INCLUDE_IMAGES,
1549b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                ImageManager.SORT_ASCENDING);
1550b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ImageManager.IImage image = list.getImageForUri(uri);
1551b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        list.deactivate();
1552b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return image;
1553b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1554b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1555b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1556b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void startReceivingLocationUpdates() {
1557b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mLocationManager != null) {
1558b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1559b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mLocationManager.requestLocationUpdates(
1560b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        LocationManager.NETWORK_PROVIDER,
1561b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        1000,
1562b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        0F,
1563b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mLocationListeners[1]);
1564b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (java.lang.SecurityException ex) {
1565b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // ok
1566b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (IllegalArgumentException ex) {
1567b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (Config.LOGD) {
1568b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.d(TAG, "provider does not exist " + ex.getMessage());
1569b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1570b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1571b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1572b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mLocationManager.requestLocationUpdates(
1573b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        LocationManager.GPS_PROVIDER,
1574b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        1000,
1575b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        0F,
1576b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mLocationListeners[0]);
1577b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (java.lang.SecurityException ex) {
1578b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // ok
1579b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (IllegalArgumentException ex) {
1580b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (Config.LOGD) {
1581b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.d(TAG, "provider does not exist " + ex.getMessage());
1582b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1583b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1584b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1585b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void stopReceivingLocationUpdates() {
1588b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mLocationManager != null) {
1589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            for (int i = 0; i < mLocationListeners.length; i++) {
1590b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
1591b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mLocationManager.removeUpdates(mLocationListeners[i]);
1592b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } catch (Exception ex) {
1593b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // ok
1594b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1596b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1597b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Location getCurrentLocation() {
1600b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Location l = null;
1601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1602b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // go in best to worst order
1603b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int i = 0; i < mLocationListeners.length; i++) {
1604b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            l = mLocationListeners[i].current();
1605b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (l != null)
1606b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
1607b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1609b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return l;
1610b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1611b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1612b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1613b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onOptionsMenuClosed(Menu menu) {
1614b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onOptionsMenuClosed(menu);
16159a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (mImageSavingItem) {
1616b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // save the image if we presented the "advanced" menu
1617b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // which happens if "menu" is pressed while in
1618b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // SNAPSHOT_IN_PROGRESS  or SNAPSHOT_COMPLETED modes
1619b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            keep();
1620b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mHandler.sendEmptyMessage(RESTART_PREVIEW);
1621b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1622b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1623b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1624b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1625b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onMenuOpened(int featureId, Menu menu) {
1626b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (featureId == Window.FEATURE_OPTIONS_PANEL) {
1627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStatus == SNAPSHOT_IN_PROGRESS) {
1628b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                cancelAutomaticPreviewRestart();
1629b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1630b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1631b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onMenuOpened(featureId, menu);
1632b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1633b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1634b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1635b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onPrepareOptionsMenu(Menu menu) {
1636b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPrepareOptionsMenu(menu);
1637b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1638b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int i = 1; i <= MenuHelper.MENU_ITEM_MAX; i++) {
1639b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (i != MenuHelper.GENERIC_ITEM) {
1640b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                menu.setGroupVisible(i, false);
1641b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1642b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1643b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1644b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mStatus == SNAPSHOT_IN_PROGRESS || mStatus == SNAPSHOT_COMPLETED) {
1645b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            menu.setGroupVisible(MenuHelper.IMAGE_SAVING_ITEM, true);
1646b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mImageSavingItem = true;
1647b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
1648b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            menu.setGroupVisible(MenuHelper.IMAGE_MODE_ITEM, true);
1649b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mImageSavingItem = false;
1650b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1651b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1652b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
1653b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1654b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1655b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void cancelAutomaticPreviewRestart() {
1656b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mKeepAndRestartPreview = false;
1657b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(RESTART_PREVIEW);
1658b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1659b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1660b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean isImageCaptureIntent() {
1661b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String action = getIntent().getAction();
1662b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action));
1663b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1665b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void showPostCaptureAlert() {
1666b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (isImageCaptureIntent()) {
1667b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostCaptureAlert.setVisibility(View.VISIBLE);
1668b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            int[] pickIds = {R.id.attach, R.id.cancel};
1669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            for(int id : pickIds) {
1670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                View view = mPostCaptureAlert.findViewById(id);
1671b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                view.setOnClickListener(this);
1672b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Animation animation = new AlphaAnimation(0F, 1F);
1673b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                animation.setDuration(500);
1674b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                view.setAnimation(animation);
1675b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1676b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1677b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1678b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1679b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void hidePostCaptureAlert() {
1680b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (isImageCaptureIntent()) {
1681b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostCaptureAlert.setVisibility(View.INVISIBLE);
1682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1683b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1684b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1685b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1686b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onCreateOptionsMenu(Menu menu) {
1687b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreateOptionsMenu(menu);
1688b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1689b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (isImageCaptureIntent()) {
1690b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // No options menu for attach mode.
1691b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
1692b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
1693b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            addBaseMenuItems(menu);
1694b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1695b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
1696b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1697b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1698b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    SelectedImageGetter mSelectedImageGetter =
1699b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        new SelectedImageGetter() {
1700b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public ImageManager.IImage getCurrentImage() {
1701b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return getImageForURI(getCurrentImageUri());
1702b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1703b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public Uri getCurrentImageUri() {
1704b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                keep();
1705b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return mCaptureObject.getLastCaptureUri();
1706b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1707b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        };
1708b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1709b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int calculatePicturesRemaining() {
1710b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPicturesRemaining = MenuHelper.calculatePicturesRemaining();
1711b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return mPicturesRemaining;
1712b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1713b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1714b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void addBaseMenuItems(Menu menu) {
1715b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.addSwitchModeMenuItem(menu, this, true);
1716b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
1717b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            MenuItem gallery = menu.add(MenuHelper.IMAGE_MODE_ITEM, MENU_GALLERY_PHOTOS, 0, R.string.camera_gallery_photos_text).setOnMenuItemClickListener(new OnMenuItemClickListener() {
1718b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                public boolean onMenuItemClick(MenuItem item) {
1719b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    gotoGallery();
1720b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
1721b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1722b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            });
1723b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
1724b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
1725b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1726b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
1727b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            MenuItem gallery = menu.add(MenuHelper.VIDEO_MODE_ITEM, MENU_GALLERY_VIDEOS, 0, R.string.camera_gallery_photos_text).setOnMenuItemClickListener(new OnMenuItemClickListener() {
1728b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                public boolean onMenuItemClick(MenuItem item) {
1729b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    gotoGallery();
1730b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
1731b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1732b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            });
1733b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
1734b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
1735b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1736b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1737b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuItem item = menu.add(MenuHelper.GENERIC_ITEM, MENU_SETTINGS, 0, R.string.settings).setOnMenuItemClickListener(new OnMenuItemClickListener() {
1738b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public boolean onMenuItemClick(MenuItem item) {
1739b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Intent intent = new Intent();
1740b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                intent.setClass(Camera.this, CameraSettings.class);
1741b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                startActivity(intent);
1742b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1743b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1744b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
1745b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        item.setIcon(android.R.drawable.ic_menu_preferences);
1746b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1747b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project}
1748b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1749