VideoCamera.java revision d55a5e92d6065bd36a60925221d8cc9a773572eb
1b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project/*
2b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
4b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * you may not use this file except in compliance with the License.
6b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * You may obtain a copy of the License at
7b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
8b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
10b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * See the License for the specific language governing permissions and
14b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * limitations under the License.
15b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */
16b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
17b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpackage com.android.camera;
18b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
19101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport com.android.camera.gallery.IImage;
20101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport com.android.camera.gallery.IImageList;
21101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
22b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.app.Activity;
23b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.BroadcastReceiver;
24b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.ContentResolver;
25b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.ContentValues;
26b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Context;
27b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Intent;
28b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.IntentFilter;
29b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.SharedPreferences;
30095afa19556bf550262e3cccb9edacc04e6f726aOwen Linimport android.database.Cursor;
31b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.Bitmap;
32b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.drawable.Drawable;
33b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.media.MediaRecorder;
34b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.net.Uri;
35b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Bundle;
36b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Environment;
37b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Handler;
38b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Message;
39b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.StatFs;
40b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.SystemClock;
41b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.preference.PreferenceManager;
42b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.provider.MediaStore;
43b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.provider.MediaStore.Video;
44b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.text.format.DateFormat;
45b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.util.Log;
46b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.KeyEvent;
47b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Menu;
48b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.MenuItem;
496b270508bdbc78a52a825c2d934465d99fb779f7Chih-Chung Changimport android.view.MenuItem.OnMenuItemClickListener;
50b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.SurfaceHolder;
51b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.View;
52b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Window;
53b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.WindowManager;
54b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.AlphaAnimation;
55b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.Animation;
56b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.ImageView;
57b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.TextView;
58b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.Toast;
59b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
60d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.io.File;
61d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.io.FileDescriptor;
62d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.io.IOException;
63d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.text.SimpleDateFormat;
64d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.util.ArrayList;
65d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.util.Date;
66d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
6723c51b794e95c201290e36737f379c4bb8eefeaeRay Chen/**
6823c51b794e95c201290e36737f379c4bb8eefeaeRay Chen * The Camcorder activity.
6923c51b794e95c201290e36737f379c4bb8eefeaeRay Chen */
70b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpublic class VideoCamera extends Activity implements View.OnClickListener,
71d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback,
72d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener {
73b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
74b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final String TAG = "videocamera";
75b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
76ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li    private static final int UPDATE_LAST_VIDEO = 3;
77b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int CLEAR_SCREEN_DELAY = 4;
78b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int UPDATE_RECORD_TIME = 5;
79b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
80b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int SCREEN_DELAY = 2 * 60 * 1000;
81b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
82b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final long NO_STORAGE_ERROR = -1L;
83b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final long CANNOT_STAT_ERROR = -2L;
84b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final long LOW_STORAGE_THRESHOLD = 512L * 1024L;
85e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    private static final long SHARE_FILE_LENGTH_LIMIT = 3L * 1024L * 1024L;
86b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private static final int STORAGE_STATUS_OK = 0;
889a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private static final int STORAGE_STATUS_LOW = 1;
899a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private static final int STORAGE_STATUS_NONE = 2;
909a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
91b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SETTINGS = 6;
92b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_PHOTOS = 7;
93b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_VIDEOS = 8;
94b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_GALLERY_PHOTO = 34;
95b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_PLAY_VIDEO = 35;
96b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_SELECT_VIDEO = 36;
97b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_NEW_VIDEO = 37;
98b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
99b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    SharedPreferences mPreferences;
100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final float VIDEO_ASPECT_RATIO = 176.0f / 144.0f;
102b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    VideoPreview mVideoPreview;
103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    SurfaceHolder mSurfaceHolder = null;
104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    ImageView mVideoFrame;
1059bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
1069bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private boolean mIsVideoCaptureIntent;
1079bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // mLastPictureButton and mThumbController
1080a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang    // are non-null only if mIsVideoCaptureIntent is true.
109de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    private ImageView mLastPictureButton;
1109bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private ThumbnailController mThumbController;
111b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
112c0701504237478f810e43012a155b3461b640e54Chih-Chung Chang    private static final int MAX_RECORDING_DURATION_MS = 600 * 60 * 1000;
1138d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
1149a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private int mStorageStatus = STORAGE_STATUS_OK;
1159a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private MediaRecorder mMediaRecorder;
117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mMediaRecorderRecording = false;
118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mRecordingStartTime;
119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // The video file that the hardware camera is about to record into
120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // (or is recording into.)
121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private String mCameraVideoFilename;
122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private FileDescriptor mCameraVideoFileDescriptor;
123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // The video file that has already been recorded, and that is being
125b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // examined by the user.
126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private String mCurrentVideoFilename;
1278d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    private long mCurrentVideoFileLength = 0L;
128b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Uri mCurrentVideoUri;
129b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ContentValues mCurrentVideoValues;
130b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
131845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    // The video frame size we will record (like 352x288).
132845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private int mVideoWidth, mVideoHeight;
133845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
134b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    boolean mPausing = false;
135ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li    boolean mPreviewing = false;  // True if preview is started.
136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
137d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private ContentResolver mContentResolver;
138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ShutterButton mShutterButton;
140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private TextView mRecordingTimeView;
1418d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    private boolean mRecordingTimeCountsDown = false;
142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    ArrayList<MenuItem> mGalleryItems = new ArrayList<MenuItem>();
144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    View mPostPictureAlert;
146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
147b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Handler mHandler = new MainHandler();
148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
149d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    // This Handler is used to post message back onto the main thread of the
150d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    // application
151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class MainHandler extends Handler {
152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void handleMessage(Message msg) {
154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            switch (msg.what) {
155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case CLEAR_SCREEN_DELAY: {
157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    clearScreenOnFlag();
158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case UPDATE_RECORD_TIME: {
162d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    updateRecordingTime();
163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
166ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                case UPDATE_LAST_VIDEO: {
167ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                    if (!mThumbController.isUriValid()) {
168ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                        updateLastVideo();
169ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                    }
170ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                    mThumbController.updateDisplayIfNeeded();
171ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                    break;
172ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                }
173ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                default:
175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.v(TAG, "Unhandled message: " + msg.what);
1760a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang                    break;
177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
179937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Lin    }
180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onReceive(Context context, Intent intent) {
184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            String action = intent.getAction();
185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (action.equals(Intent.ACTION_MEDIA_EJECT)) {
1869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(false);
187b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                stopVideoRecording();
188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                initializeVideo();
189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
1909a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(true);
191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                initializeVideo();
192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
193b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // SD card unavailable
1949a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                // handled in ACTION_MEDIA_EJECT
195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) {
196d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Toast.makeText(VideoCamera.this,
197d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        getResources().getString(R.string.wait), 5000);
198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) {
1999a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(true);
200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
201b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
203b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
204d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private static String createName(long dateTaken) {
205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString();
206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
207b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /** Called with the activity is first created. */
209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
210b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onCreate(Bundle icicle) {
211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreate(icicle);
212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
213ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        /*
214ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         * To reduce startup time, we open camera device in another thread.
215ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         * Camera is opened in onCreate instead of onResume because there are
216ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         * lots of things to do here and camera open can be done in parallel.
217ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         * We will make sure the camera is opened at the end of onCreate.
218ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         */
219ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        Thread openCameraThread = new Thread(new Runnable() {
220ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            public void run() {
221ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                mCameraDevice = android.hardware.Camera.open();
222ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            }
223ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        });
224ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        openCameraThread.start();
225ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
226b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
227b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mContentResolver = getContentResolver();
228b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
229b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        requestWindowFeature(Window.FEATURE_PROGRESS);
230b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setContentView(R.layout.video_camera);
231b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
232b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoPreview = (VideoPreview) findViewById(R.id.camera_preview);
233b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoPreview.setAspectRatio(VIDEO_ASPECT_RATIO);
234b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
235b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // don't set mSurfaceHolder here. We have it set ONLY within
236b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // surfaceCreated / surfaceDestroyed, other parts of the code
237b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // assume that when it is set, the surface is also set.
238b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SurfaceHolder holder = mVideoPreview.getHolder();
239b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.addCallback(this);
240b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
241b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
242b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPostPictureAlert = findViewById(R.id.post_picture_panel);
243b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
244b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] ids = new int[]{R.id.play, R.id.share, R.id.discard,
245b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                R.id.cancel, R.id.attach};
246b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int id : ids) {
247b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            findViewById(id).setOnClickListener(this);
248b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
249b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
250b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton = (ShutterButton) findViewById(R.id.shutter_button);
251b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setOnShutterButtonListener(this);
252b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mRecordingTimeView = (TextView) findViewById(R.id.recording_time);
253b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoFrame = (ImageView) findViewById(R.id.video_frame);
2549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mIsVideoCaptureIntent = isVideoCaptureIntent();
2559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
256d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mLastPictureButton = (ImageView) findViewById(
257d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    R.id.last_picture_button);
2589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setOnClickListener(this);
259d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            Drawable frame = getResources().getDrawable(
260d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    R.drawable.frame_thumbnail);
2619bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController = new ThumbnailController(mLastPictureButton,
2629bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    frame, mContentResolver);
2639bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.loadData(ImageManager.getLastVideoThumbPath());
2649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
265ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
266ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        // Make sure the camera is opened.
267ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        try {
268ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            openCameraThread.join();
269ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        } catch (InterruptedException ex) {
270ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // ignore
271ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        }
272b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
273b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
274e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    private void startShareVideoActivity() {
2758d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        if (mCurrentVideoFileLength > SHARE_FILE_LENGTH_LIMIT) {
276e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            Toast.makeText(VideoCamera.this,
277e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                    R.string.too_large_to_attach, Toast.LENGTH_LONG).show();
278e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            return;
279e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
280e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        Intent intent = new Intent();
281e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.setAction(Intent.ACTION_SEND);
282e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.setType("video/3gpp");
283e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.putExtra(Intent.EXTRA_STREAM, mCurrentVideoUri);
284e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        try {
285d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            startActivity(Intent.createChooser(
286d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    intent, getText(R.string.sendVideo)));
287e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        } catch (android.content.ActivityNotFoundException ex) {
288d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            Toast.makeText(VideoCamera.this, R.string.no_way_to_share_video,
289d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    Toast.LENGTH_SHORT).show();
290e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
291e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    }
292e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project
293b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onClick(View v) {
294b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (v.getId()) {
295b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
296b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.gallery:
2970a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang                gotoGallery();
298b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
300b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.attach:
301b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doReturnToCaller(true);
302b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
303b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
304b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.cancel:
305b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doReturnToCaller(false);
306b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
307b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
308b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.discard: {
3097638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                Runnable deleteCallback = new Runnable() {
3107638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                    public void run() {
3117638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                        discardCurrentVideoAndStartPreview();
3127638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                    }
3137638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                };
3147638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                MenuHelper.deleteVideo(this, deleteCallback);
315b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
316b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
317b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
318b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.share: {
319e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                startShareVideoActivity();
320b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
321b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
322b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
323b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.play: {
324b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doPlayCurrentVideo();
325b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
326b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
327de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
328de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            case R.id.last_picture_button: {
3299bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndShowAlert();
330de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                break;
331de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            }
332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
333b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
334b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
335b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onShutterButtonFocus(ShutterButton button, boolean pressed) {
336de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        // Do nothing (everything happens in onShutterButtonClick).
337de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
338de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
339de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    public void onShutterButtonClick(ShutterButton button) {
340b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (button.getId()) {
341b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.shutter_button:
342de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                if (mMediaRecorderRecording) {
3439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    if (mIsVideoCaptureIntent) {
344de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                        stopVideoRecordingAndShowAlert();
345b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } else {
3469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        stopVideoRecordingAndGetThumbnail();
3479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        initializeVideo();
3489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    }
3499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                } else if (isAlertVisible()) {
3509bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    if (mIsVideoCaptureIntent) {
3519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        discardCurrentVideoAndStartPreview();
3529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    } else {
3532687ac3dc7764260692223a247b19f9a189ace46Chih-Chung Chang                        hideAlertAndStartPreview();
354b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
355de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                } else {
356de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    startVideoRecording();
357b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
358b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
359b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
360b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
361b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
362b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doPlayCurrentVideo() {
3630a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang        Log.v(TAG, "Playing current video: " + mCurrentVideoUri);
364b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri);
365b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
366b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            startActivity(intent);
367b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (android.content.ActivityNotFoundException ex) {
368b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex);
369b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
370b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
371b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
372b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void discardCurrentVideoAndStartPreview() {
373b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        deleteCurrentVideo();
3749bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlertAndStartPreview();
375b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
376b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
377b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private OnScreenHint mStorageHint;
378b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3799a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private void updateAndShowStorageHint(boolean mayHaveSd) {
3809a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mStorageStatus = getStorageStatus(mayHaveSd);
3819a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        showStorageHint();
3829a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    }
3839a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
3849a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private void showStorageHint() {
385b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String errorMessage = null;
3869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        switch (mStorageStatus) {
3879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        case STORAGE_STATUS_NONE:
388b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            errorMessage = getString(R.string.no_storage);
3899a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            break;
3909a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        case STORAGE_STATUS_LOW:
391b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            errorMessage = getString(R.string.spaceIsLow_content);
392b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
393b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (errorMessage != null) {
394b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStorageHint == null) {
395b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint = OnScreenHint.makeText(this, errorMessage);
396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
397b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint.setText(errorMessage);
398b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
399b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.show();
400b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else if (mStorageHint != null) {
401b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
402b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
403b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
404b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
405b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4069a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private int getStorageStatus(boolean mayHaveSd) {
4079a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        long remaining = mayHaveSd ? getAvailableStorage() : NO_STORAGE_ERROR;
4089a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (remaining == NO_STORAGE_ERROR) {
4099a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            return STORAGE_STATUS_NONE;
4109a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
4119a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        return remaining < LOW_STORAGE_THRESHOLD
4129a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                ? STORAGE_STATUS_LOW : STORAGE_STATUS_OK;
4139a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    }
4149a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
415845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private void readVideoSizePreference() {
416845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        boolean videoQualityHigh = getBooleanPreference(
417845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang                CameraSettings.KEY_VIDEO_QUALITY,
418845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang                CameraSettings.DEFAULT_VIDEO_QUALITY_VALUE);
419845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
420845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        Intent intent = getIntent();
421845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) {
422845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            int extraVideoQuality = intent.getIntExtra(
423845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang                    MediaStore.EXTRA_VIDEO_QUALITY, 0);
424845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            videoQualityHigh = (extraVideoQuality > 0);
425845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
426845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
427845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        if (videoQualityHigh) {
428845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            // CIF size
429845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoWidth = 352;
430845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoHeight = 288;
431845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        } else {
432845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            // QCIF size
433845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoWidth = 176;
434845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoHeight = 144;
435845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
436845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
437845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
438b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
439b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onResume() {
440b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onResume();
441845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mPausing = false;
442b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
443b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutLong();
444845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        readVideoSizePreference();
445b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
446b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // install an intent filter to receive SD card related events.
447d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        IntentFilter intentFilter =
448d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
449b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_EJECT);
450b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
452b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
453b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addDataScheme("file");
454b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        registerReceiver(mReceiver, intentFilter);
4559a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mStorageStatus = getStorageStatus(true);
4569a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
4579a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mHandler.postDelayed(new Runnable() {
4589a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            public void run() {
4599a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                showStorageHint();
4609a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            }
4619a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }, 200);
462b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4639bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        initializeVideo();
464b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
465b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
466845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private void setCameraParameters() {
467845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        android.hardware.Camera.Parameters param;
468845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        param = mCameraDevice.getParameters();
469845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        param.setPreviewSize(mVideoWidth, mVideoHeight);
470845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice.setParameters(param);
471845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
472845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
473845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    // Precondition: mSurfaceHolder != null
474845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private void startPreview() {
475845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        Log.v(TAG, "startPreview");
476ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        if (mPreviewing) {
477d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            // We should just return here, but we stop and start again to avoid
478d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            // the bug in driver.
479d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            mCameraDevice.lock();
480d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            mCameraDevice.stopPreview();
481d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            mCameraDevice.startPreview();
482d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            mCameraDevice.unlock();
483845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            return;
484845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
485ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
486ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        if (mCameraDevice == null) {
487ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // If the activity is paused and resumed, camera device has been
488ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // released and we need to open the camera.
489ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            mCameraDevice = android.hardware.Camera.open();
490ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        }
491ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
492845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        setCameraParameters();
493845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        try {
494845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.setPreviewDisplay(mSurfaceHolder);
495845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        } catch (IOException ex) {
496845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.release();
497845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice = null;
498845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            Log.e(TAG, "failed to set preview display");
499845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            return;
500845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
501ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
502845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        try {
503845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.startPreview();
504ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            mPreviewing = true;
505845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        } catch (Throwable ex) {
506845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            // TODO: change Throwable to IOException once
507845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            //      android.hardware.Camera.startPreview properly declares
508845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            //      that it throws IOException.
509845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.release();
510845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice = null;
511845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            Log.e(TAG, "failed to start preview");
512845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            return;
513845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
514845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice.unlock();
515845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
516845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
517d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang    private void closeCamera() {
518d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang        Log.v(TAG, "closeCamera");
519845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        if (mCameraDevice == null) {
520845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            Log.d(TAG, "already stopped.");
521845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            return;
522845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
523845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice.release();
524845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice = null;
525ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        mPreviewing = false;
526845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
527845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
528b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
529b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onStop() {
530b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutSystemDefault();
531b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onStop();
532b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
533b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
534b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
535b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    protected void onPause() {
536b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPause();
537b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5389bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // This is similar to what mShutterButton.performClick() does,
5399bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // but not quite the same.
5409bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mMediaRecorderRecording) {
5419bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (mIsVideoCaptureIntent) {
5429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndShowAlert();
5439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            } else {
5449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndGetThumbnail();
5459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            }
5469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } else {
5479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            stopVideoRecording();
5489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
549b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
550b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPausing = true;
551b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5529c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        unregisterReceiver(mReceiver);
553b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutSystemDefault();
554b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
5569bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.storeData(ImageManager.getLastVideoThumbPath());
5579bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
558095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin
559b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mStorageHint != null) {
560b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
561b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
562b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
563845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
564d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang        closeCamera();
565ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
566ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        mHandler.removeMessages(UPDATE_LAST_VIDEO);
567b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
568b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
569b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
570b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
571b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutLong();
572b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
573b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (keyCode) {
574b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_BACK:
575b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mMediaRecorderRecording) {
576de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
577b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
578d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                } else if (isAlertVisible()) {
5799bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    hideAlertAndStartPreview();
580b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
581b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
582b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
583b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_CAMERA:
584b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
585de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
588de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                break;
589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_CENTER:
590b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
591de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
592de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    return true;
593b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
594b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_MENU:
596b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mMediaRecorderRecording) {
597de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
600b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
602b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
603b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyDown(keyCode, event);
604b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
605b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
606b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
607b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch(keyCode) {
609b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case KeyEvent.KEYCODE_CAMERA:
610b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mShutterButton.setPressed(false);
611b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return true;
612b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
613b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyUp(keyCode, event);
614b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
615b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
616b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
617314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber        if (mPausing) {
618314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // We're pausing, the screen is off and we already stopped
619314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // video recording. We don't want to start the camera again
620314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // in this case in order to conserve power.
621314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // The fact that surfaceChanged is called _after_ an onPause appears
622314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // to be legitimate since in that case the lockscreen always returns
623314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // to portrait orientation possibly triggering the notification.
624314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            return;
625314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber        }
626314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber
627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopVideoRecording();
628b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        initializeVideo();
629b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
630b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
631b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceCreated(SurfaceHolder holder) {
632b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = holder;
633b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
634b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
635b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceDestroyed(SurfaceHolder holder) {
636b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = null;
637b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
638b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6390a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang    private void gotoGallery() {
640b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.gotoCameraVideoGallery(this);
641b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
642b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
643b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
644b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onPrepareOptionsMenu(Menu menu) {
645b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPrepareOptionsMenu(menu);
646b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
647b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int i = 1; i <= MenuHelper.MENU_ITEM_MAX; i++) {
648b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (i != MenuHelper.GENERIC_ITEM) {
649b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                menu.setGroupVisible(i, false);
650b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
651b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
652b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
653b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        menu.setGroupVisible(MenuHelper.VIDEO_MODE_ITEM, true);
654b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
655b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
656b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
657b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
658b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onCreateOptionsMenu(Menu menu) {
659b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreateOptionsMenu(menu);
660b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6619bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent) {
662b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // No options menu for attach mode.
663b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
665b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            addBaseMenuItems(menu);
666d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int menuFlags = MenuHelper.INCLUDE_ALL
667d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    & ~MenuHelper.INCLUDE_ROTATE_MENU
668095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin                    & ~MenuHelper.INCLUDE_DETAILS_MENU;
669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            MenuHelper.addImageMenuItems(
670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    menu,
671095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin                    menuFlags,
672b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    false,
673b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    VideoCamera.this,
67423c51b794e95c201290e36737f379c4bb8eefeaeRay Chen                    mHandler,
675b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // Handler for deletion
676b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    new Runnable() {
677b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run() {
678b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            // What do we do here?
679b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            // mContentResolver.delete(uri, null, null);
680b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
681b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    },
682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    new MenuHelper.MenuInvoker() {
683b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run(final MenuHelper.MenuCallback cb) {
684b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
685b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    });
686b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
687d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.IMAGE_SAVING_ITEM,
688d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_SAVE_GALLERY_PHOTO, 0,
689d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    R.string.camera_gallery_photos_text)
690d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(
691d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    new MenuItem.OnMenuItemClickListener() {
692d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
693d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
694d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
695d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
696d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
697b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
698b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
699b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
700b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
701b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
702b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean isVideoCaptureIntent() {
703b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String action = getIntent().getAction();
704b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action));
705b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
706b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
707b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doReturnToCaller(boolean success) {
708b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent resultIntent = new Intent();
709b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int resultCode;
710b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (success) {
711b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultCode = RESULT_OK;
712b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultIntent.setData(mCurrentVideoUri);
713b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
714b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultCode = RESULT_CANCELED;
715b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
716b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setResult(resultCode, resultIntent);
717b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        finish();
718b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
719b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
720b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
721b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * Returns
722b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * @return number of bytes available, or an ERROR code.
723b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
724b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static long getAvailableStorage() {
725b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
726b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (!ImageManager.hasStorage()) {
727b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return NO_STORAGE_ERROR;
728b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
729d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                String storageDirectory = Environment
730d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        .getExternalStorageDirectory().toString();
731b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                StatFs stat = new StatFs(storageDirectory);
732d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                return ((long) stat.getAvailableBlocks()
733d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        * (long) stat.getBlockSize());
734b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
73523c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        } catch (RuntimeException ex) {
736b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // if we can't stat the filesystem then we don't know how many
737b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // free bytes exist.  It might be zero but just leave it
738b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // blank since we really don't know.
739b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return CANNOT_STAT_ERROR;
740b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
741b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
742b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
743b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void cleanupEmptyFile() {
744b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraVideoFilename != null) {
745b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            File f = new File(mCameraVideoFilename);
746b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (f.length() == 0 && f.delete()) {
747b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project              Log.v(TAG, "Empty video file deleted: " + mCameraVideoFilename);
748b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project              mCameraVideoFilename = null;
749b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
750b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
751b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
752b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
753845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private android.hardware.Camera mCameraDevice;
7549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // initializeVideo() starts preview and prepare media recorder.
755b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // Returns false if initializeVideo fails
756b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean initializeVideo() {
757b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "initializeVideo");
7589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
7599bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // We will call initializeVideo() again when the alert is hidden.
76023c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        if (isAlertVisible()) {
76123c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            return false;
76223c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        }
7639bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
764b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent intent = getIntent();
765b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bundle myExtras = intent.getExtras();
766b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
7679bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent && myExtras != null) {
768b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
769b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (saveUri != null) {
770b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
771b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCameraVideoFileDescriptor = mContentResolver.
772b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        openFileDescriptor(saveUri, "rw").getFileDescriptor();
773b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCurrentVideoUri = saveUri;
774d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                } catch (java.io.FileNotFoundException ex) {
775b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // invalid uri
776b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.e(TAG, ex.toString());
777b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
778b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
779b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
780b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        releaseMediaRecorder();
781b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
782b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mSurfaceHolder == null) {
783b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "SurfaceHolder is null");
784b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
785b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
786845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        startPreview();
787b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder = new MediaRecorder();
788b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
789845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mMediaRecorder.setCamera(mCameraDevice);
790d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
791b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
792b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
7938d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        mMediaRecorder.setMaxDuration(MAX_RECORDING_DURATION_MS);
7948d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
7959a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (mStorageStatus != STORAGE_STATUS_OK) {
796b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.setOutputFile("/dev/null");
797b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
798d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // We try Uri in intent first. If it doesn't work, use our own
799d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // instead.
800b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCameraVideoFileDescriptor != null) {
801b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOutputFile(mCameraVideoFileDescriptor);
802b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
803b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                createVideoPath();
804b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOutputFile(mCameraVideoFilename);
805b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
806b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
807b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
808b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
809b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // Use the same frame rate for both, since internally
810b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // if the frame rate is too large, it can cause camera to become
811b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // unstable. We need to fix the MediaRecorder to disable the support
812b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // of setting frame rate for now.
813b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoFrameRate(20);
814845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mMediaRecorder.setVideoSize(mVideoWidth, mVideoHeight);
815b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
816d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
817b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
818de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
819de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        long remaining = getAvailableStorage();
820de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        // remaining >= LOW_STORAGE_THRESHOLD at this point, reserve a quarter
821d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // of that to make it more likely that recording can complete
822d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // successfully.
823de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        try {
824d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mMediaRecorder.setMaxFileSize(remaining -
825d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    LOW_STORAGE_THRESHOLD / 4);
826de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        } catch (RuntimeException exception) {
827de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // We are going to ignore failure of setMaxFileSize here, as
828de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // a) The composer selected may simply not support it, or
829de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // b) The underlying media framework may not handle 64-bit range
830de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            //    on the size restriction.
831de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        }
832de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
833b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
834b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.prepare();
835b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (IOException exception) {
836b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "prepare failed for " + mCameraVideoFilename);
837b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            releaseMediaRecorder();
838b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // TODO: add more exception handling logic here
839b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
840b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
841b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorderRecording = false;
8429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
843ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        // Update the last video thumbnail.
844ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        if (!mIsVideoCaptureIntent
845ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                && !mHandler.hasMessages(UPDATE_LAST_VIDEO)) {
846ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            mHandler.sendEmptyMessage(UPDATE_LAST_VIDEO);
8479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
848b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
849b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
850b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
851b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void releaseMediaRecorder() {
852b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Releasing media recorder.");
853b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mMediaRecorder != null) {
854b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cleanupEmptyFile();
855b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.reset();
856b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.release();
857b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder = null;
858b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
859b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
860b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
861b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int getIntPreference(String key, int defaultValue) {
862b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String s = mPreferences.getString(key, "");
863b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int result = defaultValue;
864b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
865b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            result = Integer.parseInt(s);
866b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (NumberFormatException e) {
867b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Ignore, result is already the default value.
868b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
869b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return result;
870b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
871b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
872b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean getBooleanPreference(String key, boolean defaultValue) {
873b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return getIntPreference(key, defaultValue ? 1 : 0) != 0;
874b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
875b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
876b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void createVideoPath() {
877b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        long dateTaken = System.currentTimeMillis();
878b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String title = createName(dateTaken);
879b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String displayName = title + ".3gp"; // Used when emailing.
880b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME;
881b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        File cameraDir = new File(cameraDirPath);
882b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        cameraDir.mkdirs();
883b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SimpleDateFormat dateFormat = new SimpleDateFormat(
884b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                getString(R.string.video_file_name_format));
885b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Date date = new Date(dateTaken);
886b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String filepart = dateFormat.format(date);
887b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String filename = cameraDirPath + "/" + filepart + ".3gp";
888b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ContentValues values = new ContentValues(7);
889b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.TITLE, title);
890b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DISPLAY_NAME, displayName);
891b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DATE_TAKEN, dateTaken);
892b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.MIME_TYPE, "video/3gpp");
893b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DATA, filename);
894b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFilename = filename;
895b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Current camera video filename: " + mCameraVideoFilename);
896b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCurrentVideoValues = values;
897b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
898b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
899b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void registerVideo() {
900b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraVideoFileDescriptor == null) {
901b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri videoTable = Uri.parse("content://media/external/video/media");
902b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoUri = mContentResolver.insert(videoTable,
903b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCurrentVideoValues);
904b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "Current video URI: " + mCurrentVideoUri);
905b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
906b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCurrentVideoValues = null;
907b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
908b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
909b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void deleteCurrentVideo() {
910b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCurrentVideoFilename != null) {
911b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            deleteVideoFile(mCurrentVideoFilename);
912b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoFilename = null;
913b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
914b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCurrentVideoUri != null) {
915b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mContentResolver.delete(mCurrentVideoUri, null, null);
916b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoUri = null;
917b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
918de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        updateAndShowStorageHint(true);
919b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
920b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
921b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void deleteVideoFile(String fileName) {
922b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Deleting video " + fileName);
923b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        File f = new File(fileName);
924d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (!f.delete()) {
925b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "Could not delete " + fileName);
926b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
927b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
928b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
929b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void addBaseMenuItems(Menu menu) {
930b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.addSwitchModeMenuItem(menu, this, false);
931b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
932d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.IMAGE_MODE_ITEM,
933d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_GALLERY_PHOTOS, 0, R.string.camera_gallery_photos_text)
934d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
935d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
936d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
937d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
938d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
939d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
940b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
941b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
942b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
943b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
944d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.VIDEO_MODE_ITEM,
945d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_GALLERY_VIDEOS, 0, R.string.camera_gallery_photos_text)
946d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
947d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
948d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
949d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
950d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
951d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
952b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
953b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
954b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
955b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
956d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        MenuItem item = menu.add(MenuHelper.GENERIC_ITEM, MENU_SETTINGS, 0,
957d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                R.string.settings)
958d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                .setOnMenuItemClickListener(new OnMenuItemClickListener() {
959d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    public boolean onMenuItemClick(MenuItem item) {
960d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        Intent intent = new Intent();
961d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        intent.setClass(VideoCamera.this, CameraSettings.class);
962d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        startActivity(intent);
963d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        return true;
964d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    }
965d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                });
966b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        item.setIcon(android.R.drawable.ic_menu_preferences);
967b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
968b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
969b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // from MediaRecorder.OnErrorListener
970b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onError(MediaRecorder mr, int what, int extra) {
971b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) {
972b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // We may have run out of space on the sdcard.
973b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            stopVideoRecording();
9749a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            updateAndShowStorageHint(true);
975b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
976b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
977b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
9788d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    // from MediaRecorder.OnInfoListener
9798d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    public void onInfo(MediaRecorder mr, int what, int extra) {
9808d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
981de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            mShutterButton.performClick();
982d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        } else if (what
983d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
984de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            mShutterButton.performClick();
985de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            updateAndShowStorageHint(true);
9868d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        }
9878d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    }
9888d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
9899c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    /*
9909c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     * Make sure we're not recording music playing in the background, ask
9919c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     * the MediaPlaybackService to pause playback.
9929c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     */
9939c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private void pauseAudioPlayback() {
9949c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // Shamelessly copied from MediaPlaybackService.java, which
9959c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // should be public, but isn't.
9969c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        Intent i = new Intent("com.android.music.musicservicecommand");
9979c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        i.putExtra("command", "pause");
9989c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
9999c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        sendBroadcast(i);
10009c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    }
10019c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
1002b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void startVideoRecording() {
1003b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "startVideoRecording");
1004b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (!mMediaRecorderRecording) {
1005b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10069a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            if (mStorageStatus != STORAGE_STATUS_OK) {
1007b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "Storage issue, ignore the start request");
1008b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
1009b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1010b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1011b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Check mMediaRecorder to see whether it is initialized or not.
1012d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            if (mMediaRecorder == null && initializeVideo() == false) {
1013b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Initialize video (MediaRecorder) failed.");
1014b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
1015b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1016b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10179c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            pauseAudioPlayback();
10189c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
1019b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1020b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOnErrorListener(this);
10218d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                mMediaRecorder.setOnInfoListener(this);
1022b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.start();   // Recording is now started
1023b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (RuntimeException e) {
1024b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Could not start media recorder. ", e);
1025b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
1026b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1027b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorderRecording = true;
1028b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingStartTime = SystemClock.uptimeMillis();
1029b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateRecordingIndicator(true);
1030b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setText("");
1031b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setVisibility(View.VISIBLE);
1032b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mHandler.sendEmptyMessage(UPDATE_RECORD_TIME);
1033b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setScreenTimeoutInfinite();
1034de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            hideLastPictureButton();
1035ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // Last picture button is hidden. No need to update last video.
1036ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            mHandler.removeMessages(UPDATE_LAST_VIDEO);
1037b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1038b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1039b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1040b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateRecordingIndicator(boolean showRecording) {
1041d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        int drawableId = showRecording
1042d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                ? R.drawable.ic_camera_bar_indicator_record
1043d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                : R.drawable.ic_camera_indicator_video;
1044b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Drawable drawable = getResources().getDrawable(drawableId);
1045b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setImageDrawable(drawable);
1046b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1047b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void stopVideoRecordingAndGetThumbnail() {
10499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        stopVideoRecording();
10509bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        acquireVideoThumb();
1051b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1052b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1053de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    private void stopVideoRecordingAndShowAlert() {
1054de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        stopVideoRecording();
10559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        showAlert();
1056de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1057de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
10589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void showAlert() {
1059b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] pickIds = {R.id.attach, R.id.cancel};
1060b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] normalIds = {R.id.gallery, R.id.share, R.id.discard};
1061b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] alwaysOnIds = {R.id.play};
1062b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] hideIds = pickIds;
1063b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] connectIds = normalIds;
10649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent) {
1065b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            hideIds = normalIds;
1066b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            connectIds = pickIds;
1067b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1068d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        for (int id : hideIds) {
1069b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostPictureAlert.findViewById(id).setVisibility(View.GONE);
1070b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
10718d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        ActionMenuButton shareButton =
10728d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                (ActionMenuButton) mPostPictureAlert.findViewById(R.id.share);
10738d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        shareButton.setRestricted(
10748d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                mCurrentVideoFileLength > SHARE_FILE_LENGTH_LIMIT);
1075b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        connectAndFadeIn(connectIds);
1076b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        connectAndFadeIn(alwaysOnIds);
1077de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        hideLastPictureButton();
1078b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPostPictureAlert.setVisibility(View.VISIBLE);
10799bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
10809bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // There are two cases we are here:
10819bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // (1) We are in a capture video intent, and we are reviewing the video
1082095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin        //     we just taken.
10839bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // (2) The thumbnail button is clicked: we review the video associated
10849bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        //     with the thumbnail.
10859bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // For the second case, we copy the associated URI and filename to
10869bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // mCurrentVideoUri and mCurrentVideoFilename, so the video frame shown
10879bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // and the target for actions (play, delete, ...) will be correct.
10889bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
10899bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
10909bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mCurrentVideoUri = mThumbController.getUri();
10919bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mCurrentVideoFilename = getDataPath(mCurrentVideoUri);
10929bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
10939bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
10949bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        String path = mCurrentVideoFilename;
10959bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (path != null) {
1096101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            Bitmap videoFrame = Util.createVideoThumbnail(path);
10979bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mVideoFrame.setImageBitmap(videoFrame);
10989bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mVideoFrame.setVisibility(View.VISIBLE);
10999bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
1100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11029bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlert() {
1103de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mVideoFrame.setVisibility(View.INVISIBLE);
1104de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mPostPictureAlert.setVisibility(View.INVISIBLE);
1105de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        showLastPictureButton();
1106de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1107de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
1108b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void connectAndFadeIn(int[] connectIds) {
1109d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        for (int id : connectIds) {
1110b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            View view = mPostPictureAlert.findViewById(id);
1111b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            view.setOnClickListener(this);
1112b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Animation animation = new AlphaAnimation(0F, 1F);
1113b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            animation.setDuration(500);
11149bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            view.startAnimation(animation);
1115b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11189bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private boolean isAlertVisible() {
1119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return mPostPictureAlert.getVisibility() == View.VISIBLE;
1120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void stopVideoRecording() {
1123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "stopVideoRecording");
1124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean needToRegisterRecording = false;
1125b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mMediaRecorderRecording || mMediaRecorder != null) {
1126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mMediaRecorderRecording && mMediaRecorder != null) {
1127b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
1128b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mMediaRecorder.setOnErrorListener(null);
11298d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    mMediaRecorder.setOnInfoListener(null);
1130b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mMediaRecorder.stop();
1131b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } catch (RuntimeException e) {
1132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.e(TAG, "stop fail: " + e.getMessage());
1133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
11348d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
1135b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCurrentVideoFilename = mCameraVideoFilename;
11368d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                try {
1137d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    mCurrentVideoFileLength =
1138d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            new File(mCurrentVideoFilename).length();
11398d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                } catch (RuntimeException e) {
11408d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    Log.e(TAG, "get file length fail: " + e.getMessage());
11418d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    mCurrentVideoFileLength = 0;
11428d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                }
1143d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Log.v(TAG, "Setting current video filename: "
1144d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        + mCurrentVideoFilename);
1145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                needToRegisterRecording = true;
1146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorderRecording = false;
1147b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            releaseMediaRecorder();
1149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateRecordingIndicator(false);
1150b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setVisibility(View.GONE);
1151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setScreenTimeoutLong();
1152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
11539a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (needToRegisterRecording && mStorageStatus == STORAGE_STATUS_OK) {
11549a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            registerVideo();
11559a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
1156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFilename = null;
1158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFileDescriptor = null;
1159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutSystemDefault() {
1162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        clearScreenOnFlag();
1164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutLong() {
1167b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1168b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenOnFlag();
1169b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
1170b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutInfinite() {
1173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenOnFlag();
1175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void clearScreenOnFlag() {
1178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window w = getWindow();
1179d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1180d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if ((w.getAttributes().flags & flag) != 0) {
1181d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            w.clearFlags(flag);
1182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenOnFlag() {
1186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window w = getWindow();
1187d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1188d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if ((w.getAttributes().flags & flag) == 0) {
1189d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            w.addFlags(flag);
1190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11939bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlertAndStartPreview() {
11949bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlert();
11959bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        initializeVideo();
1196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11989bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlertAndStartVideoRecording() {
11999bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlert();
12009bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        startVideoRecording();
1201b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12039bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void acquireVideoThumb() {
1204101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        Bitmap videoFrame = Util.createVideoThumbnail(mCurrentVideoFilename);
12059bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mThumbController.setData(mCurrentVideoUri, videoFrame);
1206de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1207de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12089bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void showLastPictureButton() {
12099bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
12109bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setVisibility(View.VISIBLE);
1211de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        }
12129bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    }
1213de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12149bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideLastPictureButton() {
12159bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
12169bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setVisibility(View.INVISIBLE);
12179bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
1218de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1219de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12209bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static ImageManager.DataLocation dataLocation() {
12219bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        return ImageManager.DataLocation.EXTERNAL;
1222de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1223de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12249bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void updateLastVideo() {
122558e94eddd371a9bb7c04936dbeb99615fd1a0c2cChih-Chung Chang        IImageList list = ImageManager.allImages(
12269bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mContentResolver,
12279bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            dataLocation(),
12289bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.INCLUDE_VIDEOS,
12299bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.SORT_ASCENDING,
12309bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.CAMERA_IMAGE_BUCKET_ID);
12319bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        int count = list.getCount();
12329bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (count > 0) {
1233d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            IImage image = list.getImageAt(count - 1);
12349bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            Uri uri = image.fullSizeImageUri();
12359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(uri, image.miniThumbBitmap());
12369bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } else {
12379bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(null, null);
12389bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
12399bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        list.deactivate();
1240b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1241b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static final String[] DATA_PATH_PROJECTION = new String[] {
12439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        "_data"
12449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    };
12459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
12469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private String getDataPath(Uri uri) {
12479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        Cursor c = null;
12489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        try {
1249d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            c = mContentResolver.query(uri, DATA_PATH_PROJECTION, null, null,
1250d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    null);
12519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (c != null && c.moveToFirst()) {
12529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                return c.getString(0);
12539bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            } else {
12549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                return null;
12559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            }
12569bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } finally {
125723c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            if (c != null) {
125823c51b794e95c201290e36737f379c4bb8eefeaeRay Chen                c.close();
125923c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            }
1260b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1261b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1262d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1263d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private void updateRecordingTime() {
126423c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        if (!mMediaRecorderRecording) {
126523c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            return;
126623c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        }
1267d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long now = SystemClock.uptimeMillis();
1268d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long delta = now - mRecordingStartTime;
1269d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1270d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // Starting a minute before reaching the max duration
1271d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // limit, we'll countdown the remaining time instead.
1272d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        boolean countdownRemainingTime =
1273d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            (delta >= MAX_RECORDING_DURATION_MS - 60000);
1274d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1275d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (countdownRemainingTime) {
1276d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            delta = Math.max(0, MAX_RECORDING_DURATION_MS - delta);
1277d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1278d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1279d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long seconds = (delta + 500) / 1000;  // round to nearest
1280d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long minutes = seconds / 60;
1281d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long hours = minutes / 60;
1282d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long remainderMinutes = minutes - (hours * 60);
1283d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long remainderSeconds = seconds - (minutes * 60);
1284d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1285d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String secondsString = Long.toString(remainderSeconds);
1286d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (secondsString.length() < 2) {
1287d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            secondsString = "0" + secondsString;
1288d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1289d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String minutesString = Long.toString(remainderMinutes);
1290d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (minutesString.length() < 2) {
1291d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            minutesString = "0" + minutesString;
1292d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1293d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String text = minutesString + ":" + secondsString;
1294d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (hours > 0) {
1295d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            String hoursString = Long.toString(hours);
1296d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            if (hoursString.length() < 2) {
1297d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                hoursString = "0" + hoursString;
1298d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            }
1299d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            text = hoursString + ":" + text;
1300d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1301d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mRecordingTimeView.setText(text);
1302d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1303d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (mRecordingTimeCountsDown != countdownRemainingTime) {
1304d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // Avoid setting the color on every update, do it only
1305d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // when it needs changing.
1306d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1307d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mRecordingTimeCountsDown = countdownRemainingTime;
1308d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1309d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int color = getResources().getColor(
1310d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    countdownRemainingTime
1311d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    ? R.color.recording_time_remaining_text
1312d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    : R.color.recording_time_elapsed_text);
1313d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1314d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mRecordingTimeView.setTextColor(color);
1315d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1316d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1317d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // Work around a limitation of the T-Mobile G1: The T-Mobile
1318d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // hardware blitter can't pixel-accurately scale and clip at the
1319d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // same time, and the SurfaceFlinger doesn't attempt to work around
1320d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // this limitation. In order to avoid visual corruption we must
1321d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // manually refresh the entire surface view when changing any
1322d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // overlapping view's contents.
1323d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mVideoPreview.invalidate();
1324d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mHandler.sendEmptyMessageDelayed(UPDATE_RECORD_TIME, 1000);
1325d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    }
1326b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project}
1327