Camera.java revision 11c53782ca0a7be5e033bafdf0be6ac124bde8cb
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.File;
20b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.FileNotFoundException;
21b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.FileOutputStream;
22b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.IOException;
23b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.io.OutputStream;
24b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport java.util.ArrayList;
25b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
26b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.app.Activity;
27b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.BroadcastReceiver;
28b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.ContentResolver;
29b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Context;
30b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Intent;
31b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.IntentFilter;
32b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.SharedPreferences;
33b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.pm.ActivityInfo;
34b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.Bitmap;
35b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.BitmapFactory;
36b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.Matrix;
37b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.drawable.Drawable;
38b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.hardware.Camera.PictureCallback;
39b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.hardware.Camera.Size;
40b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.location.Location;
41b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.location.LocationManager;
42b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.location.LocationProvider;
43b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.media.AudioManager;
44b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.media.ToneGenerator;
45b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.net.Uri;
46b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Bundle;
47b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Debug;
48b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Environment;
49b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Handler;
50b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Message;
51b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.SystemClock;
52b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.preference.PreferenceManager;
53b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.provider.MediaStore;
54b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.text.format.DateFormat;
55b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.util.Config;
56b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.util.Log;
57b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.KeyEvent;
58b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Menu;
59b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.MenuItem;
60b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.MenuItem.OnMenuItemClickListener;
61b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.OrientationEventListener;
62b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.SurfaceHolder;
63b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.View;
64b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.ViewGroup;
65b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Window;
66b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.WindowManager;
67b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.AlphaAnimation;
68b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.Animation;
69b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.AnimationUtils;
70b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.ImageView;
71b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.Toast;
72b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
73b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpublic class Camera extends Activity implements View.OnClickListener,
74b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback {
75b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
76b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final String TAG = "camera";
77b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
78b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final boolean DEBUG = false;
79b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final boolean DEBUG_TIME_OPERATIONS = DEBUG && false;
80b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
81b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int CROP_MSG = 1;
82b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int RESTART_PREVIEW = 3;
83b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int CLEAR_SCREEN_DELAY = 4;
84b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
85b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int SCREEN_DELAY = 2 * 60 * 1000;
86b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int FOCUS_BEEP_VOLUME = 100;
87b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
88b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SWITCH_TO_VIDEO = 0;
89b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SWITCH_TO_CAMERA = 1;
90b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_FLASH_SETTING = 2;
91b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_FLASH_AUTO = 3;
92b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_FLASH_ON = 4;
93b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_FLASH_OFF = 5;
94b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SETTINGS = 6;
95b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_PHOTOS = 7;
96b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_VIDEOS = 8;
97b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_SELECT_PHOTOS = 30;
98b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_NEW_PHOTO = 31;
99b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_GALLERY_PHOTO = 34;
100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_GALLERY_VIDEO_PHOTO = 35;
101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_CAMERA_DONE = 36;
102b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_CAMERA_VIDEO_DONE = 37;
103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private OrientationEventListener mOrientationListener;
105b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mLastOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
106b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private SharedPreferences mPreferences;
107b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
108b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int IDLE = 1;
109b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int SNAPSHOT_IN_PROGRESS = 2;
110b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int SNAPSHOT_COMPLETED = 3;
111b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
112b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mStatus = IDLE;
113b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final String sTempCropFilename = "crop-temp";
114b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
115b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private android.hardware.Camera mCameraDevice;
116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private android.hardware.Camera.Parameters mParameters;
117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private VideoPreview mSurfaceView;
118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private SurfaceHolder mSurfaceHolder = null;
119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mOriginalViewFinderWidth, mOriginalViewFinderHeight;
121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mViewFinderWidth, mViewFinderHeight;
122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mPreviewing = false;
123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Capturer mCaptureObject;
125b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ImageCapture mImageCapture = null;
126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
127b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mPausing = false;
128b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1299c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUS_NOT_STARTED = 0;
1309c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUSING = 1;
1319c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUSING_SNAP_ON_FINISH = 2;
1329c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUS_SUCCESS = 3;
1339c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private static final int FOCUS_FAIL = 4;
1349c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private int mFocusState = FOCUS_NOT_STARTED;
135b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static ContentResolver mContentResolver;
137b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mDidRegister = false;
138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ArrayList<MenuItem> mGalleryItems = new ArrayList<MenuItem>();
140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private LocationManager mLocationManager = null;
142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ShutterButton mShutterButton;
144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Animation mFocusBlinkAnimation;
146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private View mFocusIndicator;
14707c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin    private ImageView mGpsIndicator;
148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ToneGenerator mFocusToneGenerator;
149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
150b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ShutterCallback mShutterCallback = new ShutterCallback();
152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private RawPictureCallback mRawPictureCallback = new RawPictureCallback();
153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private AutoFocusCallback mAutoFocusCallback = new AutoFocusCallback();
154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mFocusStartTime;
155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mFocusCallbackTime;
156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mCaptureStartTime;
157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mShutterCallbackTime;
158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mRawPictureCallbackTime;
159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int mPicturesRemaining;
16007c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin    private boolean mRecordLocation;
161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mKeepAndRestartPreview;
163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private boolean mIsImageCaptureIntent;
1659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // mPostCaptureAlert, mLastPictureButton, mThumbController
1669bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // are non-null only if isImageCaptureIntent() is true.
167b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private View mPostCaptureAlert;
1689bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private ImageView mLastPictureButton;
1699bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private ThumbnailController mThumbController;
170b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Handler mHandler = new MainHandler();
172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private interface Capturer {
174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Uri getLastCaptureUri();
175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        void onSnap();
1769a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        void dismissFreezeFrame();
177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /** This Handler is used to post message back onto the main thread of the application */
180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class MainHandler extends Handler {
181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void handleMessage(Message msg) {
183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            switch (msg.what) {
184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case RESTART_PREVIEW: {
185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (mStatus == SNAPSHOT_IN_PROGRESS) {
186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // We are still in the processing of taking the picture, wait.
187e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                        // This is strange.  Why are we polling?
188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // TODO remove polling
189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mHandler.sendEmptyMessageDelayed(RESTART_PREVIEW, 100);
190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } else if (mStatus == SNAPSHOT_COMPLETED){
1919a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                        mCaptureObject.dismissFreezeFrame();
192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        hidePostCaptureAlert();
193b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
194b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case CLEAR_SCREEN_DELAY: {
198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
201b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
203b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    LocationListener [] mLocationListeners = new LocationListener[] {
206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            new LocationListener(LocationManager.GPS_PROVIDER),
207b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            new LocationListener(LocationManager.NETWORK_PROVIDER)
208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
210b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
213b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onReceive(Context context, Intent intent) {
214b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            String action = intent.getAction();
215b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
216b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // SD card available
217b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                updateStorageHint(calculatePicturesRemaining());
218b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED) ||
219b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    action.equals(Intent.ACTION_MEDIA_CHECKING)) {
220b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // SD card unavailable
221b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mPicturesRemaining = MenuHelper.NO_STORAGE_ERROR;
222b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                updateStorageHint(mPicturesRemaining);
223b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) {
224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Toast.makeText(Camera.this, getResources().getString(R.string.wait), 5000);
225b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) {
226b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                updateStorageHint();
227b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
228b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
229b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
230b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
231b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class LocationListener implements android.location.LocationListener {
232b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Location mLastLocation;
233b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean mValid = false;
234b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String mProvider;
235b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
236b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public LocationListener(String provider) {
237b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mProvider = provider;
238b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastLocation = new Location(mProvider);
239b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
240b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
241b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onLocationChanged(Location newLocation) {
242b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (newLocation.getLatitude() == 0.0 && newLocation.getLongitude() == 0.0) {
243b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // Hack to filter out 0.0,0.0 locations
244b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
245b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
24607c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            // If GPS is available before start camera, we won't get status
24707c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            // update so update GPS indicator when we receive data.
24807c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            if (mRecordLocation
24907c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                    && LocationManager.GPS_PROVIDER.equals(mProvider)) {
25007c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                mGpsIndicator.setVisibility(View.VISIBLE);
25107c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            }
252b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastLocation.set(newLocation);
253b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mValid = true;
254b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
255b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
256b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onProviderEnabled(String provider) {
257b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
258b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
259b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onProviderDisabled(String provider) {
260b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mValid = false;
261b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
262b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
263b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onStatusChanged(String provider, int status, Bundle extras) {
26407c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            switch(status) {
26507c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                case LocationProvider.OUT_OF_SERVICE:
26607c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                case LocationProvider.TEMPORARILY_UNAVAILABLE: {
26707c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                    mValid = false;
26807c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                    if (mRecordLocation &&
26907c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                            LocationManager.GPS_PROVIDER.equals(provider)) {
27007c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                        mGpsIndicator.setVisibility(View.INVISIBLE);
27107c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                    }
27207c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                    break;
27307c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                }
274b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
275b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
276b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
277b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public Location current() {
278b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return mValid ? mLastLocation : null;
279b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
280b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
281b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
282b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mImageSavingItem = false;
283b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
284b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final class ShutterCallback implements android.hardware.Camera.ShutterCallback {
285b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onShutter() {
286b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) {
287b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mShutterCallbackTime = System.currentTimeMillis();
288b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "Shutter lag was " + (mShutterCallbackTime - mCaptureStartTime) + " ms.");
289b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
290b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
291e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            // We are going to change the size of surface view and show captured
292de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // image. Set it to invisible now and set it back to visible in
293e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            // surfaceChanged() so that users won't see the image is resized on
294e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            // the screen.
295e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            mSurfaceView.setVisibility(View.INVISIBLE);
296b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Resize the SurfaceView to the aspect-ratio of the still image
297b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // and so that we can see the full image that was taken.
298e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            Size pictureSize = mParameters.getPictureSize();
299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mSurfaceView.setAspectRatio(pictureSize.width, pictureSize.height);
300b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
301b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
302b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
303b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final class RawPictureCallback implements PictureCallback {
304b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onPictureTaken(byte [] rawData, android.hardware.Camera camera) {
305b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (Config.LOGV)
306b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "got RawPictureCallback...");
307b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRawPictureCallbackTime = System.currentTimeMillis();
308b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) {
309b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, (mRawPictureCallbackTime - mShutterCallbackTime) + "ms elapsed between" +
310b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        " ShutterCallback and RawPictureCallback.");
311b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
312b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
313b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
314b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
315b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final class JpegPictureCallback implements PictureCallback {
316b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Location mLocation;
317b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
318b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public JpegPictureCallback(Location loc) {
319b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLocation = loc;
320b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
321b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
322b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onPictureTaken(byte [] jpegData, android.hardware.Camera camera) {
323de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            if (mPausing) {
324e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                return;
325e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            }
326b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (Config.LOGV)
327b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "got JpegPictureCallback...");
328b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
329b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) {
330b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                long mJpegPictureCallback = System.currentTimeMillis();
331b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, (mJpegPictureCallback - mRawPictureCallbackTime) + "ms elapsed between" +
332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        " RawPictureCallback and JpegPictureCallback.");
333b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
334b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
335de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            if (jpegData != null) {
336de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                mImageCapture.storeImage(jpegData, camera, mLocation);
337de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            }
338b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
339b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStatus = SNAPSHOT_COMPLETED;
340b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
341b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mKeepAndRestartPreview) {
342b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                long delay = 1500 - (System.currentTimeMillis() - mRawPictureCallbackTime);
343b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mHandler.sendEmptyMessageDelayed(RESTART_PREVIEW, Math.max(delay, 0));
344b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
345b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
346b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
347b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
348b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final class AutoFocusCallback implements android.hardware.Camera.AutoFocusCallback {
349b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onAutoFocus(boolean focused, android.hardware.Camera camera) {
350b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) {
351b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mFocusCallbackTime = System.currentTimeMillis();
352b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "Auto focus took " + (mFocusCallbackTime - mFocusStartTime) + " ms.");
353b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
354b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3559c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            if (mFocusState == FOCUSING_SNAP_ON_FINISH && mCaptureObject != null) {
3569c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // Take the picture no matter focus succeeds or fails.
3579c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // No need to play the AF sound if we're about to play the shutter sound.
3589c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                mCaptureObject.onSnap();
3599c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                clearFocusState();
3609c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            } else if (mFocusState == FOCUSING) {
3619c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // User is half-pressing the focus key. Play the focus tone.
3629c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // Do not take the picture now.
3639c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                ToneGenerator tg = mFocusToneGenerator;
3649c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                if (tg != null)
3659c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                   tg.startTone(ToneGenerator.TONE_PROP_BEEP2);
3669c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                if (focused) {
3679c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusState = FOCUS_SUCCESS;
368b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
3699c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                else {
3709c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusState = FOCUS_FAIL;
3719c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                }
3729c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            } else if (mFocusState == FOCUS_NOT_STARTED) {
3739c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // User has released the focus key before focus completes.
3749c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // Do nothing.
375de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            }
376b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateFocusIndicator();
377b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
378b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
379b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
380b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class ImageCapture implements Capturer {
381b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
382b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private boolean mCancel = false;
383b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private boolean mCapturing = false;
384b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
385b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private Uri mLastContentUri;
386b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private ImageManager.IAddImage_cancelable mAddImageCancelable;
387b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
388b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bitmap mCaptureOnlyBitmap;
389b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
390b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        /** These member variables are used for various debug timings */
391b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private long mThreadTimeStart;
392b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private long mThreadTimeEnd;
393b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private long mWallTimeStart;
394b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private long mWallTimeEnd;
395b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
397b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public ImageCapture() {
398b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
399b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
400b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        /**
401b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         * This method sets whether or not we are capturing a picture. This method must be called
402b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         * with the ImageCapture.this lock held.
403b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         */
404b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void setCapturingLocked(boolean capturing) {
405b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCapturing = capturing;
406b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
407b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4089a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        public void dismissFreezeFrame() {
409b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStatus == SNAPSHOT_IN_PROGRESS) {
410b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // If we are still in the process of taking a picture, then just post a message.
411b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mHandler.sendEmptyMessage(RESTART_PREVIEW);
412b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
413b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                restartPreview();
414b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
415b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
416b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
417b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private void startTiming() {
418b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mWallTimeStart = SystemClock.elapsedRealtime();
419b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mThreadTimeStart = Debug.threadCpuTimeNanos();
420b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
421b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
422b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private void stopTiming() {
423b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mThreadTimeEnd = Debug.threadCpuTimeNanos();
424b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mWallTimeEnd = SystemClock.elapsedRealtime();
425b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
426b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
427b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private void storeImage(byte[] data, Location loc) {
428b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
429b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
430b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    startTiming();
431b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
432b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                long dateTaken = System.currentTimeMillis();
433b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                String name = createName(dateTaken) + ".jpg";
434b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mLastContentUri = ImageManager.instance().addImage(
435b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        Camera.this,
436b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mContentResolver,
437b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        name,
438b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        "",
439b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        dateTaken,
440b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // location for the database goes here
441b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        loc,
442b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        0,   // the dsp will use the right orientation so don't "double set it"
443b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        ImageManager.CAMERA_IMAGE_BUCKET_NAME,
444b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        name);
445b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
446b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mLastContentUri == null) {
447b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // this means we got an error
448b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCancel = true;
449b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
450b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (!mCancel) {
451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mAddImageCancelable = ImageManager.instance().storeImage(mLastContentUri,
452b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            Camera.this, mContentResolver, 0, null, data);
453b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mAddImageCancelable.get();
454b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mAddImageCancelable = null;
455b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
456b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
457b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
458b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    stopTiming();
459b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.d(TAG, "Storing image took " + (mWallTimeEnd - mWallTimeStart) + " ms. " +
460b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            "Thread time was " + ((mThreadTimeEnd - mThreadTimeStart) / 1000000) +
461b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            " ms.");
462b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
463b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (Exception ex) {
464b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Exception while compressing image.", ex);
465b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
466b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
467b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
468b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void storeImage(byte[] data, android.hardware.Camera camera, Location loc) {
4699bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            boolean captureOnly = mIsImageCaptureIntent;
470b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
471b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (!captureOnly) {
472b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                storeImage(data, loc);
473b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                sendBroadcast(new Intent("com.android.camera.NEW_PICTURE", mLastContentUri));
474b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setLastPictureThumb(data, mCaptureObject.getLastCaptureUri());
4759a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                dismissFreezeFrame();
476b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
477b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                BitmapFactory.Options options = new BitmapFactory.Options();
478b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                options.inSampleSize = 4;
479b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
480b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
481b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    startTiming();
482b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
483b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
484b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCaptureOnlyBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
485b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
486b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
487b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    stopTiming();
488b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.d(TAG, "Decoded mCaptureOnly bitmap (" + mCaptureOnlyBitmap.getWidth() +
489b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            "x" + mCaptureOnlyBitmap.getHeight() + " ) in " +
490b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            (mWallTimeEnd - mWallTimeStart) + " ms. Thread time was " +
491b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            ((mThreadTimeEnd - mThreadTimeStart) / 1000000) + " ms.");
492b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
493b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
494b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                showPostCaptureAlert();
495b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                cancelAutomaticPreviewRestart();
496b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
497b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
498b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCapturing = false;
499b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mPausing) {
500b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                closeCamera();
501b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
502b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
503b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
504b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        /*
505b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         * Initiate the capture of an image.
506b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         */
507b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void initiate(boolean captureOnly) {
50811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            if (mCameraDevice == null) {
50911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                return;
51011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            }
51111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
512b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCancel = false;
513b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCapturing = true;
51411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
515b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            capture(captureOnly);
516b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
517b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
518b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public Uri getLastCaptureUri() {
519b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return mLastContentUri;
520b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
521b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
522b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public Bitmap getLastBitmap() {
523b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return mCaptureOnlyBitmap;
524b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
525b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
526b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        private void capture(boolean captureOnly) {
527b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPreviewing = false;
528b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCaptureOnlyBitmap = null;
529b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
530b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            final int latchedOrientation = ImageManager.roundOrientation(mLastOrientation + 90);
531b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
53207c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            Location loc = mRecordLocation ? getCurrentLocation() : null;
533b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Quality 75 has visible artifacts, and quality 90 looks great but the files begin to
534b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // get large. 85 is a good compromise between the two.
535b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParameters.set("jpeg-quality", 85);
536b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParameters.set("rotation", latchedOrientation);
537b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
538b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParameters.remove("gps-latitude");
539b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParameters.remove("gps-longitude");
540b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParameters.remove("gps-altitude");
541b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParameters.remove("gps-timestamp");
542b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
543b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (loc != null) {
544b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                double lat = loc.getLatitude();
545b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                double lon = loc.getLongitude();
546b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                boolean hasLatLon = (lat != 0.0d) || (lon != 0.0d);
547b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
548b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (hasLatLon) {
549b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    String latString = String.valueOf(lat);
550b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    String lonString = String.valueOf(lon);
551b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mParameters.set("gps-latitude",  latString);
552b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mParameters.set("gps-longitude", lonString);
553d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                    if (loc.hasAltitude()) {
554b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mParameters.set("gps-altitude",  String.valueOf(loc.getAltitude()));
555d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                    } else {
556d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                        // for NETWORK_PROVIDER location provider, we may have
557d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                        // no altitude information, but the driver needs it, so
558d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                        // we fake one.
559d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                        mParameters.set("gps-altitude",  "0");
560d7e9d1916fbabaecd4be9dacb4472fa3ffe62ed4The Android Open Source Project                    }
561b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (loc.getTime() != 0) {
562b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // Location.getTime() is UTC in milliseconds.
563b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        // gps-timestamp is UTC in seconds.
564b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        long utcTimeSeconds = loc.getTime() / 1000;
565b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mParameters.set("gps-timestamp", String.valueOf(utcTimeSeconds));
566b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
567b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } else {
568b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    loc = null;
569b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
570b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
571b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
572b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.setParameters(mParameters);
573b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
574b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback, new JpegPictureCallback(loc));
575b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
576b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
577b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onSnap() {
578de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            if (mPausing) {
579e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                return;
580e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            }
581b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (DEBUG_TIME_OPERATIONS) mCaptureStartTime = System.currentTimeMillis();
582b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
583b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // If we are already in the middle of taking a snapshot then we should just save
584b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // the image after we have returned from the camera service.
585b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStatus == SNAPSHOT_IN_PROGRESS || mStatus == SNAPSHOT_COMPLETED) {
586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mKeepAndRestartPreview = true;
587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mHandler.sendEmptyMessage(RESTART_PREVIEW);
588b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
590b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
591b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Don't check the filesystem here, we can't afford the latency. Instead, check the
592b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // cached value which was calculated when the preview was restarted.
593b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mPicturesRemaining < 1) {
594b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                updateStorageHint(mPicturesRemaining);
595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
596b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
597b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStatus = SNAPSHOT_IN_PROGRESS;
599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
600b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mKeepAndRestartPreview = true;
601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6029bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            boolean getContentAction = mIsImageCaptureIntent;
603b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (getContentAction) {
604b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mImageCapture.initiate(true);
605b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
606b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mImageCapture.initiate(false);
607b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
609de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
6109a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        private void clearLastBitmap() {
6119a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            if (mCaptureOnlyBitmap != null) {
6129a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                mCaptureOnlyBitmap.recycle();
6139a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                mCaptureOnlyBitmap = null;
6149a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            }
6159a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
616b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
617b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
618b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setLastPictureThumb(byte[] data, Uri uri) {
619b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        BitmapFactory.Options options = new BitmapFactory.Options();
620b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        options.inSampleSize = 16;
621b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bitmap lastPictureThumb = BitmapFactory.decodeByteArray(data, 0, data.length, options);
6229bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mThumbController.setData(uri, lastPictureThumb);
623b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
624b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
625b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    static private String createName(long dateTaken) {
626b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString();
627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
628b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
629b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    static public Matrix GetDisplayMatrix(Bitmap b, ImageView v) {
630b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Matrix m = new Matrix();
631b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        float bw = (float)b.getWidth();
632b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        float bh = (float)b.getHeight();
633b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        float vw = (float)v.getWidth();
634b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        float vh = (float)v.getHeight();
635b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        float scale, x, y;
636b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (bw*vh > vw*bh) {
637b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            scale = vh / bh;
638b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            x = (vw - scale*bw)*0.5F;
639b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            y = 0;
640b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
641b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            scale = vw / bw;
642b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            x = 0;
643b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            y = (vh - scale*bh)*0.5F;
644b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
645b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        m.setScale(scale, scale, 0.5F, 0.5F);
646b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        m.postTranslate(x, y);
647b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return m;
648b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
649b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
650b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /** Called with the activity is first created. */
651b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
652b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onCreate(Bundle icicle) {
653b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreate(icicle);
654b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
65511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        // To reduce startup time, we open camera device in another thread.
65611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        // We make sure the camera is opened at the end of onCreate.
65711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        Thread openCameraThread = new Thread(new Runnable() {
65811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            public void run() {
65911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                mCameraDevice = android.hardware.Camera.open();
66011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            }
66111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        });
66211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        openCameraThread.start();
66311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // To reduce startup time, we run some service creation code in another thread.
665b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // We make sure the services are loaded at the end of onCreate().
666b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Thread loadServiceThread = new Thread(new Runnable() {
667b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public void run() {
668b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mOrientationListener = new OrientationEventListener(Camera.this) {
670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    public void onOrientationChanged(int orientation) {
6719c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                        // We keep the last known orientation. So if the user
6729c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                        // first orient the camera then point the camera to
6739c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                        // floor/sky, we still have the correct orientation.
6749c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                        if (orientation != ORIENTATION_UNKNOWN)
6759c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                            mLastOrientation = orientation;
676b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
677b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                };
678b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
679b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
680b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        loadServiceThread.start();
681b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
683b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mContentResolver = getContentResolver();
684b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
685b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window win = getWindow();
686b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
687b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setContentView(R.layout.camera);
688b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
689b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceView = (VideoPreview) findViewById(R.id.camera_preview);
69007c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin        mGpsIndicator = (ImageView) findViewById(R.id.gps_indicator);
691b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
692b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // don't set mSurfaceHolder here. We have it set ONLY within
693b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // surfaceCreated / surfaceDestroyed, other parts of the code
694b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // assume that when it is set, the surface is also set.
695b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SurfaceHolder holder = mSurfaceView.getHolder();
696b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.addCallback(this);
697b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
698b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6999bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mIsImageCaptureIntent = isImageCaptureIntent();
7009bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
7019bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsImageCaptureIntent)  {
702b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastPictureButton = (ImageView) findViewById(R.id.last_picture_button);
703b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mLastPictureButton.setOnClickListener(this);
7049bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            Drawable frame = getResources().getDrawable(R.drawable.frame_thumbnail);
7059bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController = new ThumbnailController(mLastPictureButton,
7069bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    frame, mContentResolver);
7079bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.loadData(ImageManager.getLastImageThumbPath());
708b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
709b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
710b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton = (ShutterButton) findViewById(R.id.shutter_button);
711b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setOnShutterButtonListener(this);
712b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
713b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mFocusIndicator = findViewById(R.id.focus_indicator);
714b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mFocusBlinkAnimation = AnimationUtils.loadAnimation(this, R.anim.auto_focus_blink);
715b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mFocusBlinkAnimation.setRepeatCount(Animation.INFINITE);
716b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mFocusBlinkAnimation.setRepeatMode(Animation.REVERSE);
717b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
718b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // We load the post_picture_panel layout only if it is needed.
7199bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsImageCaptureIntent) {
720b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ViewGroup cameraView = (ViewGroup)findViewById(R.id.camera);
721b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            getLayoutInflater().inflate(R.layout.post_picture_panel,
722b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                                        cameraView);
723b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostCaptureAlert = findViewById(R.id.post_picture_panel);
724b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
725b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
726b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // Make sure the services are loaded.
727b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
72811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            openCameraThread.join();
729b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            loadServiceThread.join();
730b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (InterruptedException ex) {
731b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
732b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
733b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ImageManager.ensureOSXCompatibleFolder();
734b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
735b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
736b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
737b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onStart() {
738b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onStart();
739b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
740b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Thread t = new Thread(new Runnable() {
741b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public void run() {
742b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                final boolean storageOK = calculatePicturesRemaining() > 0;
743b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
744b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (!storageOK) {
745b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mHandler.post(new Runnable() {
746b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run() {
747b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            updateStorageHint(mPicturesRemaining);
748b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
749b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    });
750b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
751b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
752b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
753b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        t.start();
754b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
755b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
756b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onClick(View v) {
757b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (v.getId()) {
758b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case R.id.last_picture_button:
759087497fca0f048f0191cb02e2838819bf210a875Chih-Chung Chang            if (mStatus == IDLE && mFocusState == FOCUS_NOT_STARTED) {
760087497fca0f048f0191cb02e2838819bf210a875Chih-Chung Chang                viewLastImage();
761087497fca0f048f0191cb02e2838819bf210a875Chih-Chung Chang            }
762b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            break;
763b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case R.id.attach:
764b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            doAttach();
765b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            break;
766b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case R.id.cancel:
767b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            doCancel();
768b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
769b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
770b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
771b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doAttach() {
772de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        if (mPausing) {
773e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            return;
774e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
775b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bitmap bitmap = mImageCapture.getLastBitmap();
776b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
777b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String cropValue = null;
778b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Uri saveUri = null;
779b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
780b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bundle myExtras = getIntent().getExtras();
781b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (myExtras != null) {
782b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
783b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cropValue = myExtras.getString("crop");
784b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
785b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
786b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
787b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (cropValue == null) {
788b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            /*
789b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project             * First handle the no crop case -- just return the value.  If the caller
790b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project             * specifies a "save uri" then write the data to it's stream.  Otherwise,
791b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project             * pass back a scaled down version of the bitmap directly in the extras.
792b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project             */
793b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (saveUri != null) {
794b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                OutputStream outputStream = null;
795b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
796b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    outputStream = mContentResolver.openOutputStream(saveUri);
797b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    bitmap.compress(Bitmap.CompressFormat.JPEG, 75, outputStream);
798b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    outputStream.close();
799b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
800b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    setResult(RESULT_OK);
801b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    finish();
802b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } catch (IOException ex) {
803b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    //
804b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } finally {
805b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (outputStream != null) {
806b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        try {
807b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            outputStream.close();
808b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        } catch (IOException ex) {
809b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
810b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
811b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
812b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
813b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
814b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                float scale = .5F;
815b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Matrix m = new Matrix();
816b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                m.setScale(scale, scale);
817b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
818b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                bitmap = Bitmap.createBitmap(bitmap, 0, 0,
819b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        bitmap.getWidth(),
820b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        bitmap.getHeight(),
821b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        m, true);
822b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
823b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setResult(RESULT_OK, new Intent("inline-data").putExtra("data", bitmap));
824b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                finish();
825b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
826b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
827b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        else {
828b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            /*
829b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project             * Save the image to a temp file and invoke the cropper
830b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project             */
831b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri tempUri = null;
832b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            FileOutputStream tempStream = null;
833b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
834b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                File path = getFileStreamPath(sTempCropFilename);
835b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                path.delete();
836b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                tempStream = openFileOutput(sTempCropFilename, 0);
837b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                bitmap.compress(Bitmap.CompressFormat.JPEG, 75, tempStream);
838b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                tempStream.close();
839b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                tempUri = Uri.fromFile(path);
840b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (FileNotFoundException ex) {
841b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setResult(Activity.RESULT_CANCELED);
842b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                finish();
843b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
844b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (IOException ex) {
845b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setResult(Activity.RESULT_CANCELED);
846b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                finish();
847b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
848b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } finally {
849b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (tempStream != null) {
850b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    try {
851b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        tempStream.close();
852b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } catch (IOException ex) {
853b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
854b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
855b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
856b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
857b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
858b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Bundle newExtras = new Bundle();
859b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (cropValue.equals("circle"))
860b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                newExtras.putString("circleCrop", "true");
861b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (saveUri != null)
862b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, saveUri);
863b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            else
864b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                newExtras.putBoolean("return-data", true);
865b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
866b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Intent cropIntent = new Intent();
867b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cropIntent.setClass(Camera.this, CropImage.class);
868b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cropIntent.setData(tempUri);
869b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cropIntent.putExtras(newExtras);
870b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
871b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            startActivityForResult(cropIntent, CROP_MSG);
872b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
873b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
874b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
875b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doCancel() {
876b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setResult(RESULT_CANCELED, new Intent());
877b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        finish();
878b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
879b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
880b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onShutterButtonFocus(ShutterButton button, boolean pressed) {
88111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if (mPausing) {
882e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            return;
883e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
884b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (button.getId()) {
885b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.shutter_button:
886b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doFocus(pressed);
887b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
888b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
889b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
890b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
891b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onShutterButtonClick(ShutterButton button) {
89211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if (mPausing) {
893e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            return;
894e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
895b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (button.getId()) {
896b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.shutter_button:
8979c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                doSnap();
898b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
899b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
900b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
901b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
902b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateStorageHint() {
903b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project      updateStorageHint(MenuHelper.calculatePicturesRemaining());
904b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
905b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
906b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private OnScreenHint mStorageHint;
907b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
908b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateStorageHint(int remaining) {
909b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String noStorageText = null;
910b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
911b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (remaining == MenuHelper.NO_STORAGE_ERROR) {
912b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            String state = Environment.getExternalStorageState();
913b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (state == Environment.MEDIA_CHECKING) {
914b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                noStorageText = getString(R.string.preparing_sd);
915b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
916b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                noStorageText = getString(R.string.no_storage);
917b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
918b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else if (remaining < 1) {
919b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            noStorageText = getString(R.string.not_enough_space);
920b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
921b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
922b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (noStorageText != null) {
923b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStorageHint == null) {
924b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint = OnScreenHint.makeText(this, noStorageText);
925b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
926b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint.setText(noStorageText);
927b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
928b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.show();
929b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else if (mStorageHint != null) {
930b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
931b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
932b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
933b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
934b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
935b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
936b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onResume() {
937b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onResume();
938b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
939b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
940b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPausing = false;
941b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mOrientationListener.enable();
94207c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin        mRecordLocation = mPreferences.getBoolean(
94307c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin                "pref_camera_recordlocation_key", false);
94407c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin        mGpsIndicator.setVisibility(View.INVISIBLE);
945b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
946b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // install an intent filter to receive SD card related events.
947b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
948b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
949b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
950b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
951b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_CHECKING);
952b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addDataScheme("file");
953b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        registerReceiver(mReceiver, intentFilter);
954b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mDidRegister = true;
955b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
956b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mImageCapture = new ImageCapture();
957b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
958b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        restartPreview();
959b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
96007c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin        if (mRecordLocation) startReceivingLocationUpdates();
961b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
962b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        updateFocusIndicator();
963b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
964b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
965b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mFocusToneGenerator = new ToneGenerator(AudioManager.STREAM_SYSTEM, FOCUS_BEEP_VOLUME);
966b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (RuntimeException e) {
967b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.w(TAG, "Exception caught while creating local tone generator: " + e);
968b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mFocusToneGenerator = null;
969b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
970b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
971b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
9729bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static ImageManager.DataLocation dataLocation() {
973b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return ImageManager.DataLocation.EXTERNAL;
974b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
975b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
976b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
977b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onStop() {
978b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        keep();
979b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopPreview();
980b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        closeCamera();
981b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
982b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onStop();
983b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
984b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
985b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
986b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    protected void onPause() {
987b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        keep();
988b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
989b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPausing = true;
990b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mOrientationListener.disable();
991b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
992b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopPreview();
993b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
994b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (!mImageCapture.mCapturing) {
995b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            closeCamera();
996b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
997b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mDidRegister) {
998b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            unregisterReceiver(mReceiver);
999b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mDidRegister = false;
1000b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1001b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopReceivingLocationUpdates();
1002b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1003b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mFocusToneGenerator != null) {
1004b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mFocusToneGenerator.release();
1005b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mFocusToneGenerator = null;
1006b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1007b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10089bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsImageCaptureIntent) {
10099bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.storeData(ImageManager.getLastImageThumbPath());
10109bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
10119bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
1012b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mStorageHint != null) {
1013b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
1014b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
1015b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1016de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
10179a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        // If we are in an image capture intent and has taken
10189a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        // a picture, we just clear it in onPause.
10199a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mImageCapture.clearLastBitmap();
10209a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mImageCapture = null;
10219a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        hidePostCaptureAlert();
1022e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project
1023b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPause();
1024b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1025b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1026b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1027b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
1028b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (requestCode) {
1029b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case CROP_MSG: {
1030b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Intent intent = new Intent();
1031b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (data != null) {
1032b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Bundle extras = data.getExtras();
1033b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    if (extras != null) {
1034b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        intent.putExtras(extras);
1035b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
1036b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1037b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                setResult(resultCode, intent);
1038b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                finish();
1039b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1040b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                File path = getFileStreamPath(sTempCropFilename);
1041b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                path.delete();
1042b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1043b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
1044b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1045b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1046b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1047b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1048b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void autoFocus() {
1049b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        updateFocusIndicator();
10509c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        if (mFocusState != FOCUSING && mFocusState != FOCUSING_SNAP_ON_FINISH) {
1051b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCameraDevice != null) {
1052b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (DEBUG_TIME_OPERATIONS) {
1053b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mFocusStartTime = System.currentTimeMillis();
1054b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
10559c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                mFocusState = FOCUSING;
10569c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                mCameraDevice.autoFocus(mAutoFocusCallback);
1057b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1058b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1059b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1060b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10619c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private void clearFocusState() {
10629c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        mFocusState = FOCUS_NOT_STARTED;
1063b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1064b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1065b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateFocusIndicator() {
1066b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.post(new Runnable() {
1067b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public void run() {
10689c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                if (mFocusState == FOCUS_SUCCESS) {
10699c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.setVisibility(View.VISIBLE);
1070b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mFocusIndicator.clearAnimation();
10719c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                } else if (mFocusState == FOCUS_FAIL) {
10729c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.setVisibility(View.VISIBLE);
10739c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.startAnimation(mFocusBlinkAnimation);
1074b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } else {
10759c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.setVisibility(View.GONE);
10769c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                    mFocusIndicator.clearAnimation();
1077b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1078b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1079b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
1080b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1081b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1082b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1083b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1084b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
1085b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
1086b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
1087b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1088b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (keyCode) {
1089b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_BACK:
1090b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mStatus == SNAPSHOT_IN_PROGRESS) {
1091b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // ignore backs while we're taking a picture
1092b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
1093b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1094b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
1095b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_FOCUS:
1096b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
109711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    doFocus(true);
1098b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1099b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_CAMERA:
1101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
110211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    doSnap();
1103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1105b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_CENTER:
1106b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // If we get a dpad center event without any focused view, move the
1107b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // focus to the shutter button and press it.
1108b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
1109b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // Start auto-focus immediately to reduce shutter lag. After the shutter button
1110b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // gets the focus, doFocus() will be called again but it is fine.
111111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    doFocus(true);
111211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    if (mShutterButton.isInTouchMode()) {
111311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        mShutterButton.requestFocusFromTouch();
111411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    } else {
111511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        mShutterButton.requestFocus();
1116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
111711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    mShutterButton.setPressed(true);
1118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyDown(keyCode, event);
1123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1125b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
1127b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (keyCode) {
1128b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_FOCUS:
1129b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doFocus(false);
1130b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1131b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyUp(keyCode, event);
1133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1134b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11359c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private void doSnap() {
11369c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // If the user has half-pressed the shutter and focus is completed, we
11379c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // can take the photo right away.
1138de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        if ((mFocusState == FOCUS_SUCCESS || mFocusState == FOCUS_FAIL)
11399c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                || !mPreviewing) {
1140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // doesn't get set until the idler runs
1141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCaptureObject != null) {
1142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCaptureObject.onSnap();
1143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
11449c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            clearFocusState();
1145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateFocusIndicator();
11468d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        } else if (mFocusState == FOCUSING) {
1147de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // Half pressing the shutter (i.e. the focus button event) will
1148de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // already have requested AF for us, so just request capture on
11499c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            // focus here.
11509c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            mFocusState = FOCUSING_SNAP_ON_FINISH;
11518d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        } else if (mFocusState == FOCUS_NOT_STARTED) {
11528d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project            // Focus key down event is dropped for some reasons. Just ignore.
1153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doFocus(boolean pressed) {
11579c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        if (pressed) {  // Focus key down.
1158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mPreviewing) {
1159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                autoFocus();
1160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (mCaptureObject != null) {
1161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // Save and restart preview
1162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCaptureObject.onSnap();
1163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
11649c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        } else {  // Focus key up.
11659c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            if (mFocusState != FOCUSING_SNAP_ON_FINISH) {
11669c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                // User releases half-pressed focus key.
11679c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                clearFocusState();
11689c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project                updateFocusIndicator();
11699c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            }
1170b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
1174e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        mSurfaceView.setVisibility(View.VISIBLE);
1175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // if we're creating the surface, start the preview as well.
1176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean preview = holder.isCreating();
1177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setViewFinder(w, h, preview);
1178de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mCaptureObject = mImageCapture;
1179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceCreated(SurfaceHolder holder) {
1182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = holder;
1183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceDestroyed(SurfaceHolder holder) {
1186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopPreview();
1187b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = null;
1188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void closeCamera() {
1191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraDevice != null) {
1192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice.release();
1193b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCameraDevice = null;
1194b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPreviewing = false;
1195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
119811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks    private boolean ensureCameraDevice() {
119911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if (mCameraDevice == null) {
120011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice = android.hardware.Camera.open();
120111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        }
120211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        return mCameraDevice != null;
120311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks    }
120411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
1205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateLastImage() {
1206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ImageManager.IImageList list = ImageManager.instance().allImages(
1207b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            this,
1208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mContentResolver,
1209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            dataLocation(),
1210b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ImageManager.INCLUDE_IMAGES,
1211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ImageManager.SORT_ASCENDING,
1212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ImageManager.CAMERA_IMAGE_BUCKET_ID);
1213b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int count = list.getCount();
1214b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (count > 0) {
1215b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            ImageManager.IImage image = list.getImageAt(count-1);
12169bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            Uri uri = image.fullSizeImageUri();
12179bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(uri, image.miniThumbBitmap());
1218b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
12199bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(null, null);
1220b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1221b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        list.deactivate();
1222b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1223b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void restartPreview() {
1225b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        VideoPreview surfaceView = mSurfaceView;
1226b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1227b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // make sure the surfaceview fills the whole screen when previewing
1228b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        surfaceView.setAspectRatio(VideoPreview.DONT_CARE);
1229b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setViewFinder(mOriginalViewFinderWidth, mOriginalViewFinderHeight, true);
1230b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mStatus = IDLE;
1231b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1232b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // Calculate this in advance of each shot so we don't add to shutter latency. It's true that
1233b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // someone else could write to the SD card in the mean time and fill it, but that could have
1234b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // happened between the shutter press and saving the JPEG too.
1235b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // TODO: The best longterm solution is to write a reserve file of maximum JPEG size, always
1236b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // let the user take a picture, and delete that file if needed to save the new photo.
1237b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        calculatePicturesRemaining();
1238b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12399bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsImageCaptureIntent && !mThumbController.isUriValid()) {
1240b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateLastImage();
1241b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1242de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsImageCaptureIntent) {
12449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.updateDisplayIfNeeded();
1245b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1246b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1247b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1248b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setViewFinder(int w, int h, boolean startPreview) {
1249b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mPausing)
1250b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1251b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1252b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mPreviewing &&
1253b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                w == mViewFinderWidth &&
1254b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                h == mViewFinderHeight) {
1255b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1256b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1257b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
125811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if (!ensureCameraDevice())
125911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            return;
126011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
1261b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mSurfaceHolder == null)
1262b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1263b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1264b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (isFinishing())
1265b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1266b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1267b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mPausing)
1268b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1269b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1270b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // remember view finder size
1271b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mViewFinderWidth = w;
1272b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mViewFinderHeight = h;
1273b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mOriginalViewFinderHeight == 0) {
1274b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mOriginalViewFinderWidth = w;
1275b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mOriginalViewFinderHeight = h;
1276b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1277b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1278b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (startPreview == false)
1279b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return;
1280b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1281b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        /*
128211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks         * start the preview if we're asked to...
1283b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project         */
1284b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
128511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        // we want to start the preview and we're previewing already,
128611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        // stop the preview first (this will blank the screen).
128711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if (mPreviewing)
128811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            stopPreview();
1289b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
129011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        // this blanks the screen if the surface changed, no-op otherwise
129111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        try {
129211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice.setPreviewDisplay(mSurfaceHolder);
129311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        } catch (IOException exception) {
129411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice.release();
129511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice = null;
129611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            // TODO: add more exception handling logic here
129711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            return;
129811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        }
1299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
130011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        // request the preview size, the hardware may not honor it,
130111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        // if we depended on it we would have to query the size again
130211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        mParameters = mCameraDevice.getParameters();
130311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        mParameters.setPreviewSize(w, h);
130411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        try {
130511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice.setParameters(mParameters);
130611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        } catch (IllegalArgumentException e) {
130711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            // Ignore this error, it happens in the simulator.
130811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        }
1309b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1310b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
131111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        final long wallTimeStart = SystemClock.elapsedRealtime();
131211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        final long threadTimeStart = Debug.threadCpuTimeNanos();
1313f5e26bbc592503f28933941740c29070fa6222aeDave Sparks
131411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        final Object watchDogSync = new Object();
131511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        Thread watchDog = new Thread(new Runnable() {
131611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            public void run() {
131711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                int next_warning = 1;
131811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                while (true) {
131911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    try {
132011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        synchronized (watchDogSync) {
132111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                            watchDogSync.wait(1000);
1322b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
132311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    } catch (InterruptedException ex) {
132411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        //
1325b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
132611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    if (mPreviewing) break;
1327b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
132811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    int delay = (int) (SystemClock.elapsedRealtime() - wallTimeStart) / 1000;
132911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    if (delay >= next_warning) {
133011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        if (delay < 120) {
133111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                            Log.e(TAG, "preview hasn't started yet in " + delay + " seconds");
133211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        } else {
133311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                            Log.e(TAG, "preview hasn't started yet in " + (delay / 60) + " minutes");
133411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        }
133511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        if (next_warning < 60) {
133611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                            next_warning <<= 1;
133711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                            if (next_warning == 16) {
133811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                                next_warning = 15;
133911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                            }
134011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        } else {
134111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                            next_warning += 60;
134211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                        }
134311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    }
134411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                }
1345f5e26bbc592503f28933941740c29070fa6222aeDave Sparks            }
134611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        });
134711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
134811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        watchDog.start();
134911c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
135011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if (Config.LOGV)
135111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            Log.v(TAG, "calling mCameraDevice.startPreview");
135211c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        try {
135311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice.startPreview();
135411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        } catch (Throwable e) {
135511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            // TODO: change Throwable to IOException once android.hardware.Camera.startPreview
135611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            // properly declares that it throws IOException.
1357b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
135811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        mPreviewing = true;
1359b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
136011c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        synchronized (watchDogSync) {
136111c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            watchDogSync.notify();
1362b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
136311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks
136411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        long threadTimeEnd = Debug.threadCpuTimeNanos();
136511c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        long wallTimeEnd = SystemClock.elapsedRealtime();
136611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if ((wallTimeEnd - wallTimeStart) > 3000) {
136711c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            Log.w(TAG, "startPreview() to " + (wallTimeEnd - wallTimeStart) + " ms. Thread time was"
136811c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks                    + (threadTimeEnd - threadTimeStart) / 1000000 + " ms.");
1369b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1370b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1371b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1372b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void stopPreview() {
137311c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        if (mCameraDevice != null && mPreviewing) {
137411c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks            mCameraDevice.stopPreview();
1375b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
137611c53782ca0a7be5e033bafdf0be6ac124bde8cbDave Sparks        mPreviewing = false;
13778d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        // If auto focus was in progress, it would have been canceled.
1378de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        clearFocusState();
1379b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1380b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1381b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    void gotoGallery() {
1382b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.gotoCameraImageGallery(this);
1383b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1384b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1385b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void viewLastImage() {
13869bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mThumbController.isUriValid()) {
13879bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            Uri targetUri = mThumbController.getUri();
1388b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            targetUri = targetUri.buildUpon().
1389b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                appendQueryParameter("bucketId", ImageManager.CAMERA_IMAGE_BUCKET_ID).build();
1390b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Intent intent = new Intent(Intent.ACTION_VIEW, targetUri);
1391b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            intent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION,
1392b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
1393b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            intent.putExtra(MediaStore.EXTRA_FULL_SCREEN, true);
1394b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            intent.putExtra(MediaStore.EXTRA_SHOW_ACTION_ICONS, true);
1395b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            intent.putExtra("com.android.camera.ReviewMode", true);
1396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1397b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1398b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                startActivity(intent);
1399b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (android.content.ActivityNotFoundException ex) {
1400b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // ignore.
1401b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1402b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
1403b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "Can't view last image.");
1404b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1405b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1406b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1407b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    void keep() {
1408b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCaptureObject != null) {
14099a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            mCaptureObject.dismissFreezeFrame();
1410b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1411b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
1412b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1413b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ImageManager.IImage getImageForURI(Uri uri) {
1414b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ImageManager.IImageList list = ImageManager.instance().allImages(
1415b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                this,
1416b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mContentResolver,
1417b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                dataLocation(),
1418b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                ImageManager.INCLUDE_IMAGES,
1419b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                ImageManager.SORT_ASCENDING);
1420b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ImageManager.IImage image = list.getImageForUri(uri);
1421b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        list.deactivate();
1422b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return image;
1423b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1424b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1425b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1426b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void startReceivingLocationUpdates() {
1427b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mLocationManager != null) {
1428b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1429b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mLocationManager.requestLocationUpdates(
1430b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        LocationManager.NETWORK_PROVIDER,
1431b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        1000,
1432b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        0F,
1433b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mLocationListeners[1]);
1434b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (java.lang.SecurityException ex) {
1435b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // ok
1436b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (IllegalArgumentException ex) {
1437b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (Config.LOGD) {
1438b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.d(TAG, "provider does not exist " + ex.getMessage());
1439b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1440b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1441b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1442b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mLocationManager.requestLocationUpdates(
1443b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        LocationManager.GPS_PROVIDER,
1444b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        1000,
1445b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        0F,
1446b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        mLocationListeners[0]);
1447b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (java.lang.SecurityException ex) {
1448b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // ok
1449b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (IllegalArgumentException ex) {
1450b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (Config.LOGD) {
1451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.d(TAG, "provider does not exist " + ex.getMessage());
1452b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1453b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1454b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1455b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1456b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1457b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void stopReceivingLocationUpdates() {
1458b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mLocationManager != null) {
1459b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            for (int i = 0; i < mLocationListeners.length; i++) {
1460b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
1461b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mLocationManager.removeUpdates(mLocationListeners[i]);
1462b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } catch (Exception ex) {
1463b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // ok
1464b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1465b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1466b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1467b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1468b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1469b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Location getCurrentLocation() {
1470b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // go in best to worst order
1471b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int i = 0; i < mLocationListeners.length; i++) {
147207c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            Location l = mLocationListeners[i].current();
147307c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin            if (l != null) return l;
1474b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
147507c90568c7b0568e6cb75559bd13e5d000ac040fOwen Lin        return null;
1476b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1477b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1478b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1479b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onOptionsMenuClosed(Menu menu) {
1480b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onOptionsMenuClosed(menu);
14819a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (mImageSavingItem) {
1482b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // save the image if we presented the "advanced" menu
1483b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // which happens if "menu" is pressed while in
1484b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // SNAPSHOT_IN_PROGRESS  or SNAPSHOT_COMPLETED modes
1485b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            keep();
1486b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mHandler.sendEmptyMessage(RESTART_PREVIEW);
1487b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1488b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1489b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1490b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1491b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onMenuOpened(int featureId, Menu menu) {
1492b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (featureId == Window.FEATURE_OPTIONS_PANEL) {
1493b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStatus == SNAPSHOT_IN_PROGRESS) {
1494b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                cancelAutomaticPreviewRestart();
1495b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1496b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1497b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onMenuOpened(featureId, menu);
1498b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1499b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1500b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1501b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onPrepareOptionsMenu(Menu menu) {
1502b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPrepareOptionsMenu(menu);
1503b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1504b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int i = 1; i <= MenuHelper.MENU_ITEM_MAX; i++) {
1505b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (i != MenuHelper.GENERIC_ITEM) {
1506b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                menu.setGroupVisible(i, false);
1507b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1508b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1509b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1510b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mStatus == SNAPSHOT_IN_PROGRESS || mStatus == SNAPSHOT_COMPLETED) {
1511b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            menu.setGroupVisible(MenuHelper.IMAGE_SAVING_ITEM, true);
1512b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mImageSavingItem = true;
1513b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
1514b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            menu.setGroupVisible(MenuHelper.IMAGE_MODE_ITEM, true);
1515b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mImageSavingItem = false;
1516b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1517b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1518b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
1519b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1520b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1521b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void cancelAutomaticPreviewRestart() {
1522b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mKeepAndRestartPreview = false;
1523b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(RESTART_PREVIEW);
1524b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1525b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1526b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean isImageCaptureIntent() {
1527b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String action = getIntent().getAction();
1528b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action));
1529b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1530b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1531b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void showPostCaptureAlert() {
15329bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsImageCaptureIntent) {
1533b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostCaptureAlert.setVisibility(View.VISIBLE);
1534b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            int[] pickIds = {R.id.attach, R.id.cancel};
1535b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            for(int id : pickIds) {
1536b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                View view = mPostCaptureAlert.findViewById(id);
1537b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                view.setOnClickListener(this);
1538b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Animation animation = new AlphaAnimation(0F, 1F);
1539b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                animation.setDuration(500);
1540b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                view.setAnimation(animation);
1541b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1542b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1543b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1544b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1545b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void hidePostCaptureAlert() {
15469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsImageCaptureIntent) {
1547b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostCaptureAlert.setVisibility(View.INVISIBLE);
1548b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1549b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1550b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1551b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
1552b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onCreateOptionsMenu(Menu menu) {
1553b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreateOptionsMenu(menu);
1554b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
15559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsImageCaptureIntent) {
1556b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // No options menu for attach mode.
1557b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
1558b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
1559b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            addBaseMenuItems(menu);
1560b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1561b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
1562b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1563b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1564b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    SelectedImageGetter mSelectedImageGetter =
1565b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        new SelectedImageGetter() {
1566b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public ImageManager.IImage getCurrentImage() {
1567b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return getImageForURI(getCurrentImageUri());
1568b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1569b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public Uri getCurrentImageUri() {
1570b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                keep();
1571b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return mCaptureObject.getLastCaptureUri();
1572b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1573b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        };
1574b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1575b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int calculatePicturesRemaining() {
1576b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPicturesRemaining = MenuHelper.calculatePicturesRemaining();
1577b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return mPicturesRemaining;
1578b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1579b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1580b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void addBaseMenuItems(Menu menu) {
1581b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.addSwitchModeMenuItem(menu, this, true);
1582b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
1583b64d345c9d51cabce43b5191532a0c185d2a70a5The 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() {
1584b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                public boolean onMenuItemClick(MenuItem item) {
1585b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    gotoGallery();
1586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
1587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1588b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            });
1589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
1590b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
1591b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1592b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
1593b64d345c9d51cabce43b5191532a0c185d2a70a5The 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() {
1594b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                public boolean onMenuItemClick(MenuItem item) {
1595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    gotoGallery();
1596b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
1597b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
1598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            });
1599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
1600b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
1601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1602b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1603b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuItem item = menu.add(MenuHelper.GENERIC_ITEM, MENU_SETTINGS, 0, R.string.settings).setOnMenuItemClickListener(new OnMenuItemClickListener() {
1604b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            public boolean onMenuItemClick(MenuItem item) {
1605b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Intent intent = new Intent();
1606b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                intent.setClass(Camera.this, CameraSettings.class);
1607b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                startActivity(intent);
1608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return true;
1609b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1610b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        });
1611b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        item.setIcon(android.R.drawable.ic_menu_preferences);
1612b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1613b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project}
1614b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1615