VideoCamera.java revision 059daa36dc6e83ca24a16d9b99925e71010bcceb
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;
49b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.SurfaceHolder;
50b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.View;
51b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Window;
52b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.WindowManager;
53059daa36dc6e83ca24a16d9b99925e71010bccebOwen Linimport android.view.MenuItem.OnMenuItemClickListener;
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
1129a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private int mStorageStatus = STORAGE_STATUS_OK;
1139a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
114b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private MediaRecorder mMediaRecorder;
115b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mMediaRecorderRecording = false;
116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mRecordingStartTime;
117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // The video file that the hardware camera is about to record into
118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // (or is recording into.)
119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private String mCameraVideoFilename;
120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private FileDescriptor mCameraVideoFileDescriptor;
121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // The video file that has already been recorded, and that is being
123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // examined by the user.
124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private String mCurrentVideoFilename;
1258d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    private long mCurrentVideoFileLength = 0L;
126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Uri mCurrentVideoUri;
127b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ContentValues mCurrentVideoValues;
128b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
129845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    // The video frame size we will record (like 352x288).
130845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private int mVideoWidth, mVideoHeight;
131845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
13282ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang    // The video duration limit.
13382ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang    private int mMaxVideoDurationInMs;
13482ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang
135b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    boolean mPausing = false;
136ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li    boolean mPreviewing = false;  // True if preview is started.
137b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
138d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private ContentResolver mContentResolver;
139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ShutterButton mShutterButton;
141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private TextView mRecordingTimeView;
1428d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    private boolean mRecordingTimeCountsDown = false;
143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    ArrayList<MenuItem> mGalleryItems = new ArrayList<MenuItem>();
145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    View mPostPictureAlert;
147b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
148059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin    private final Handler mHandler = new MainHandler();
149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
150d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    // This Handler is used to post message back onto the main thread of the
151d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    // application
152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class MainHandler extends Handler {
153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void handleMessage(Message msg) {
155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            switch (msg.what) {
156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case CLEAR_SCREEN_DELAY: {
158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    clearScreenOnFlag();
159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case UPDATE_RECORD_TIME: {
163d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    updateRecordingTime();
164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
167ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                case UPDATE_LAST_VIDEO: {
168ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                    if (!mThumbController.isUriValid()) {
169ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                        updateLastVideo();
170ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                    }
171ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                    mThumbController.updateDisplayIfNeeded();
172ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                    break;
173ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                }
174ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                default:
176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.v(TAG, "Unhandled message: " + msg.what);
1770a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang                    break;
178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
180937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Lin    }
181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onReceive(Context context, Intent intent) {
185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            String action = intent.getAction();
186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (action.equals(Intent.ACTION_MEDIA_EJECT)) {
1879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(false);
188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                stopVideoRecording();
189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                initializeVideo();
190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
1919a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(true);
192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                initializeVideo();
193b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
194b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // SD card unavailable
1959a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                // handled in ACTION_MEDIA_EJECT
196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) {
197d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Toast.makeText(VideoCamera.this,
198d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        getResources().getString(R.string.wait), 5000);
199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) {
2009a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(true);
201b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
203b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
205d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private static String createName(long dateTaken) {
206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString();
207b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /** Called with the activity is first created. */
210b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onCreate(Bundle icicle) {
212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreate(icicle);
213b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
214ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        /*
215ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         * To reduce startup time, we open camera device in another thread.
216ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         * Camera is opened in onCreate instead of onResume because there are
217ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         * lots of things to do here and camera open can be done in parallel.
218ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         * We will make sure the camera is opened at the end of onCreate.
219ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         */
220ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        Thread openCameraThread = new Thread(new Runnable() {
221ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            public void run() {
222ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                mCameraDevice = android.hardware.Camera.open();
223ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            }
224ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        });
225ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        openCameraThread.start();
226ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
227b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
228b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mContentResolver = getContentResolver();
229b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
230b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        requestWindowFeature(Window.FEATURE_PROGRESS);
231b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setContentView(R.layout.video_camera);
232b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
233b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoPreview = (VideoPreview) findViewById(R.id.camera_preview);
234b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoPreview.setAspectRatio(VIDEO_ASPECT_RATIO);
235b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
236b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // don't set mSurfaceHolder here. We have it set ONLY within
237b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // surfaceCreated / surfaceDestroyed, other parts of the code
238b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // assume that when it is set, the surface is also set.
239b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SurfaceHolder holder = mVideoPreview.getHolder();
240b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.addCallback(this);
241b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
242b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
243b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPostPictureAlert = findViewById(R.id.post_picture_panel);
244b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
245b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] ids = new int[]{R.id.play, R.id.share, R.id.discard,
246b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                R.id.cancel, R.id.attach};
247b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int id : ids) {
248b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            findViewById(id).setOnClickListener(this);
249b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
250b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
251059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.video_indicator).setVisibility(View.VISIBLE);
252059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        mShutterButton = (ShutterButton) findViewById(R.id.video_button);
253b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setOnShutterButtonListener(this);
254059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        mShutterButton.requestFocus();
255059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin
256b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mRecordingTimeView = (TextView) findViewById(R.id.recording_time);
257b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoFrame = (ImageView) findViewById(R.id.video_frame);
2589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mIsVideoCaptureIntent = isVideoCaptureIntent();
2599bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
260059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            mLastPictureButton = (ImageView) findViewById(R.id.review_button);
2619bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setOnClickListener(this);
262059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            mThumbController = new ThumbnailController(
263059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin                    mLastPictureButton, mContentResolver);
2649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.loadData(ImageManager.getLastVideoThumbPath());
265059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            findViewById(R.id.camera_button).setOnClickListener(this);
266059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        } else {
267059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            findViewById(R.id.camera_button).setVisibility(View.INVISIBLE);
268059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            findViewById(R.id.review_button).setVisibility(View.INVISIBLE);
2699bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
270ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
271ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        // Make sure the camera is opened.
272ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        try {
273ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            openCameraThread.join();
274ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        } catch (InterruptedException ex) {
275ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // ignore
276ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        }
277b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
278b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
279e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    private void startShareVideoActivity() {
2808d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        if (mCurrentVideoFileLength > SHARE_FILE_LENGTH_LIMIT) {
281e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            Toast.makeText(VideoCamera.this,
282e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                    R.string.too_large_to_attach, Toast.LENGTH_LONG).show();
283e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            return;
284e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
285e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        Intent intent = new Intent();
286e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.setAction(Intent.ACTION_SEND);
287e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.setType("video/3gpp");
288e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.putExtra(Intent.EXTRA_STREAM, mCurrentVideoUri);
289e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        try {
290d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            startActivity(Intent.createChooser(
291d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    intent, getText(R.string.sendVideo)));
292e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        } catch (android.content.ActivityNotFoundException ex) {
293d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            Toast.makeText(VideoCamera.this, R.string.no_way_to_share_video,
294d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    Toast.LENGTH_SHORT).show();
295e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
296e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    }
297e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project
298b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onClick(View v) {
299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (v.getId()) {
300059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            case R.id.camera_button:
301059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin                MenuHelper.gotoCameraMode(this);
302059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin                break;
303b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
304b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.gallery:
3050a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang                gotoGallery();
306b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
307b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
308b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.attach:
309b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doReturnToCaller(true);
310b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
311b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
312b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.cancel:
313b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doReturnToCaller(false);
314b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
315b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
316b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.discard: {
3177638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                Runnable deleteCallback = new Runnable() {
3187638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                    public void run() {
3197638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                        discardCurrentVideoAndStartPreview();
3207638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                    }
3217638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                };
3227638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                MenuHelper.deleteVideo(this, deleteCallback);
323b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
324b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
325b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
326b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.share: {
327e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                startShareVideoActivity();
328b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
329b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
330b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
331b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.play: {
332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doPlayCurrentVideo();
333b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
334b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
335de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
336059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            case R.id.review_button: {
3379bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndShowAlert();
338de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                break;
339de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            }
340b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
341b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
342b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
343b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onShutterButtonFocus(ShutterButton button, boolean pressed) {
344de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        // Do nothing (everything happens in onShutterButtonClick).
345de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
346de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
347de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    public void onShutterButtonClick(ShutterButton button) {
348b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (button.getId()) {
349059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            case R.id.video_button:
350de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                if (mMediaRecorderRecording) {
3519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    if (mIsVideoCaptureIntent) {
352de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                        stopVideoRecordingAndShowAlert();
353b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } else {
3549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        stopVideoRecordingAndGetThumbnail();
3559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        initializeVideo();
3569bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    }
3579bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                } else if (isAlertVisible()) {
3589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    if (mIsVideoCaptureIntent) {
3599bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        discardCurrentVideoAndStartPreview();
3609bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    } else {
3612687ac3dc7764260692223a247b19f9a189ace46Chih-Chung Chang                        hideAlertAndStartPreview();
362b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
363de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                } else {
364de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    startVideoRecording();
365b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
366b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
367b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
368b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
369b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
370b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doPlayCurrentVideo() {
3710a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang        Log.v(TAG, "Playing current video: " + mCurrentVideoUri);
372b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri);
373b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
374b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            startActivity(intent);
375b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (android.content.ActivityNotFoundException ex) {
376b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex);
377b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
378b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
379b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
380b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void discardCurrentVideoAndStartPreview() {
381b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        deleteCurrentVideo();
3829bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlertAndStartPreview();
383b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
384b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
385b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private OnScreenHint mStorageHint;
386b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private void updateAndShowStorageHint(boolean mayHaveSd) {
3889a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mStorageStatus = getStorageStatus(mayHaveSd);
3899a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        showStorageHint();
3909a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    }
3919a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
3929a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private void showStorageHint() {
393b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String errorMessage = null;
3949a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        switch (mStorageStatus) {
3959a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        case STORAGE_STATUS_NONE:
396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            errorMessage = getString(R.string.no_storage);
3979a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            break;
3989a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        case STORAGE_STATUS_LOW:
399b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            errorMessage = getString(R.string.spaceIsLow_content);
400b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
401b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (errorMessage != null) {
402b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStorageHint == null) {
403b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint = OnScreenHint.makeText(this, errorMessage);
404b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
405b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint.setText(errorMessage);
406b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
407b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.show();
408b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else if (mStorageHint != null) {
409b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
410b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
411b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
412b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
413b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4149a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private int getStorageStatus(boolean mayHaveSd) {
4159a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        long remaining = mayHaveSd ? getAvailableStorage() : NO_STORAGE_ERROR;
4169a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (remaining == NO_STORAGE_ERROR) {
4179a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            return STORAGE_STATUS_NONE;
4189a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
4199a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        return remaining < LOW_STORAGE_THRESHOLD
4209a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                ? STORAGE_STATUS_LOW : STORAGE_STATUS_OK;
4219a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    }
4229a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
423845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private void readVideoSizePreference() {
424845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        boolean videoQualityHigh = getBooleanPreference(
425845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang                CameraSettings.KEY_VIDEO_QUALITY,
426845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang                CameraSettings.DEFAULT_VIDEO_QUALITY_VALUE);
427845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
42882ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang        // 1 minute = 60000ms
42982ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang        mMaxVideoDurationInMs = 60000 * getIntPreference(
43082ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang                CameraSettings.KEY_VIDEO_DURATION,
43182ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang                CameraSettings.DEFAULT_VIDEO_DURATION_VALUE);
43282ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang
433845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        Intent intent = getIntent();
434845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) {
435845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            int extraVideoQuality = intent.getIntExtra(
436845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang                    MediaStore.EXTRA_VIDEO_QUALITY, 0);
437845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            videoQualityHigh = (extraVideoQuality > 0);
438845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
439845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
440845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        if (videoQualityHigh) {
441845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            // CIF size
442845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoWidth = 352;
443845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoHeight = 288;
444845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        } else {
445845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            // QCIF size
446845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoWidth = 176;
447845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoHeight = 144;
448845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
449845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
450845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
452b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onResume() {
453b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onResume();
454845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mPausing = false;
455b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
456b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutLong();
457845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        readVideoSizePreference();
458b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
459b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // install an intent filter to receive SD card related events.
460d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        IntentFilter intentFilter =
461d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
462b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_EJECT);
463b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
464b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
465b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
466b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addDataScheme("file");
467b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        registerReceiver(mReceiver, intentFilter);
4689a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mStorageStatus = getStorageStatus(true);
4699a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
4709a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mHandler.postDelayed(new Runnable() {
4719a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            public void run() {
4729a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                showStorageHint();
4739a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            }
4749a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }, 200);
475b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4769bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        initializeVideo();
477b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
478b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
479845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private void setCameraParameters() {
480845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        android.hardware.Camera.Parameters param;
481845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        param = mCameraDevice.getParameters();
482845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        param.setPreviewSize(mVideoWidth, mVideoHeight);
483845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice.setParameters(param);
484845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
485845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
486845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    // Precondition: mSurfaceHolder != null
487acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang    // Returns true if starting preview succeeds.
488acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang    private boolean startPreview() {
489059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.review_indicator).setVisibility(View.INVISIBLE);
490059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.video_indicator).setVisibility(View.VISIBLE);
491059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin
492845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        Log.v(TAG, "startPreview");
493ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        if (mPreviewing) {
494d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            // We should just return here, but we stop and start again to avoid
495d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            // the bug in driver.
496d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            mCameraDevice.lock();
497d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            mCameraDevice.stopPreview();
498d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            mCameraDevice.startPreview();
499d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            mCameraDevice.unlock();
500acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang            return true;
501845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
502ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
503ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        if (mCameraDevice == null) {
504ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // If the activity is paused and resumed, camera device has been
505ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // released and we need to open the camera.
506ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            mCameraDevice = android.hardware.Camera.open();
507ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        }
508ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
509845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        setCameraParameters();
510845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        try {
511845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.setPreviewDisplay(mSurfaceHolder);
512845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        } catch (IOException ex) {
513845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.release();
514845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice = null;
515845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            Log.e(TAG, "failed to set preview display");
516acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang            return false;
517845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
518ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
519845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        try {
520845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.startPreview();
521ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            mPreviewing = true;
522845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        } catch (Throwable ex) {
523845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            // TODO: change Throwable to IOException once
524845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            //      android.hardware.Camera.startPreview properly declares
525845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            //      that it throws IOException.
526845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.release();
527845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice = null;
528845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            Log.e(TAG, "failed to start preview");
529acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang            return false;
530845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
531845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice.unlock();
532acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang        return true;
533845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
534845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
535d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang    private void closeCamera() {
536d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang        Log.v(TAG, "closeCamera");
537845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        if (mCameraDevice == null) {
538845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            Log.d(TAG, "already stopped.");
539845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            return;
540845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
541845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice.release();
542845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice = null;
543ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        mPreviewing = false;
544845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
545845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
546b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
547b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onStop() {
548b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutSystemDefault();
549b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onStop();
550b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
551b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
552b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
553b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    protected void onPause() {
554b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPause();
555b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5569bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // This is similar to what mShutterButton.performClick() does,
5579bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // but not quite the same.
5589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mMediaRecorderRecording) {
5599bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (mIsVideoCaptureIntent) {
5609bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndShowAlert();
5619bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            } else {
5629bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndGetThumbnail();
5639bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            }
5649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } else {
5659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            stopVideoRecording();
5669bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
567b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
568b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPausing = true;
569b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5709c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        unregisterReceiver(mReceiver);
571b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutSystemDefault();
572b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5739bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
5749bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.storeData(ImageManager.getLastVideoThumbPath());
5759bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
576095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin
577b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mStorageHint != null) {
578b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
579b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
580b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
581845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
582d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang        closeCamera();
583ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
584ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        mHandler.removeMessages(UPDATE_LAST_VIDEO);
585b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
588b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutLong();
590b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
591b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (keyCode) {
592b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_BACK:
593b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mMediaRecorderRecording) {
594de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
596d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                } else if (isAlertVisible()) {
5979bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    hideAlertAndStartPreview();
598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
600b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_CAMERA:
602b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
603de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
604b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
605b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
606de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                break;
607b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_CENTER:
608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
609de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
610de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    return true;
611b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
612b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
613b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_MENU:
614b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mMediaRecorderRecording) {
615de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
616b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
617b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
618b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
619b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
620b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
621b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyDown(keyCode, event);
622b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
623b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
624b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
625b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
626b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch(keyCode) {
627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case KeyEvent.KEYCODE_CAMERA:
628b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mShutterButton.setPressed(false);
629b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return true;
630b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
631b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyUp(keyCode, event);
632b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
633b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
634b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
635314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber        if (mPausing) {
636314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // We're pausing, the screen is off and we already stopped
637314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // video recording. We don't want to start the camera again
638314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // in this case in order to conserve power.
639314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // The fact that surfaceChanged is called _after_ an onPause appears
640314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // to be legitimate since in that case the lockscreen always returns
641314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // to portrait orientation possibly triggering the notification.
642314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            return;
643314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber        }
644314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber
645b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopVideoRecording();
646b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        initializeVideo();
647b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
648b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
649b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceCreated(SurfaceHolder holder) {
650b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = holder;
651b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
652b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
653b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceDestroyed(SurfaceHolder holder) {
654b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = null;
655b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
656b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6570a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang    private void gotoGallery() {
658b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.gotoCameraVideoGallery(this);
659b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
660b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
661b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
662b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onPrepareOptionsMenu(Menu menu) {
663b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPrepareOptionsMenu(menu);
664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
665b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int i = 1; i <= MenuHelper.MENU_ITEM_MAX; i++) {
666b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (i != MenuHelper.GENERIC_ITEM) {
667b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                menu.setGroupVisible(i, false);
668b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
671b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        menu.setGroupVisible(MenuHelper.VIDEO_MODE_ITEM, true);
672b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
673b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
674b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
675b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
676b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onCreateOptionsMenu(Menu menu) {
677b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreateOptionsMenu(menu);
678b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6799bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent) {
680b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // No options menu for attach mode.
681b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
683b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            addBaseMenuItems(menu);
684d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int menuFlags = MenuHelper.INCLUDE_ALL
685d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    & ~MenuHelper.INCLUDE_ROTATE_MENU
686095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin                    & ~MenuHelper.INCLUDE_DETAILS_MENU;
687b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            MenuHelper.addImageMenuItems(
688b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    menu,
689095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin                    menuFlags,
690b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    false,
691b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    VideoCamera.this,
69223c51b794e95c201290e36737f379c4bb8eefeaeRay Chen                    mHandler,
693b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // Handler for deletion
694b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    new Runnable() {
695b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run() {
696b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            // What do we do here?
697b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            // mContentResolver.delete(uri, null, null);
698b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
699b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    },
700b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    new MenuHelper.MenuInvoker() {
701b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run(final MenuHelper.MenuCallback cb) {
702b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
703b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    });
704b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
705d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.IMAGE_SAVING_ITEM,
706d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_SAVE_GALLERY_PHOTO, 0,
707d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    R.string.camera_gallery_photos_text)
708d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(
709d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    new MenuItem.OnMenuItemClickListener() {
710d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
711d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
712d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
713d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
714d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
715b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
716b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
717b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
718b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
719b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
720b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean isVideoCaptureIntent() {
721b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String action = getIntent().getAction();
722b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action));
723b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
724b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
725b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doReturnToCaller(boolean success) {
726b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent resultIntent = new Intent();
727b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int resultCode;
728b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (success) {
729b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultCode = RESULT_OK;
730b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultIntent.setData(mCurrentVideoUri);
731b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
732b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultCode = RESULT_CANCELED;
733b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
734b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setResult(resultCode, resultIntent);
735b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        finish();
736b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
737b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
738b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
739b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * Returns
740b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * @return number of bytes available, or an ERROR code.
741b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
742b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static long getAvailableStorage() {
743b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
744b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (!ImageManager.hasStorage()) {
745b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return NO_STORAGE_ERROR;
746b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
747d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                String storageDirectory = Environment
748d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        .getExternalStorageDirectory().toString();
749b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                StatFs stat = new StatFs(storageDirectory);
750d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                return ((long) stat.getAvailableBlocks()
751d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        * (long) stat.getBlockSize());
752b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
75323c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        } catch (RuntimeException ex) {
754b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // if we can't stat the filesystem then we don't know how many
755b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // free bytes exist.  It might be zero but just leave it
756b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // blank since we really don't know.
757b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return CANNOT_STAT_ERROR;
758b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
759b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
760b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
761b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void cleanupEmptyFile() {
762b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraVideoFilename != null) {
763b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            File f = new File(mCameraVideoFilename);
764b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (f.length() == 0 && f.delete()) {
765b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project              Log.v(TAG, "Empty video file deleted: " + mCameraVideoFilename);
766b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project              mCameraVideoFilename = null;
767b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
768b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
769b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
770b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
771845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private android.hardware.Camera mCameraDevice;
7729bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // initializeVideo() starts preview and prepare media recorder.
773b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // Returns false if initializeVideo fails
774b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean initializeVideo() {
775b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "initializeVideo");
7769bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
7779bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // We will call initializeVideo() again when the alert is hidden.
77823c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        if (isAlertVisible()) {
77923c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            return false;
78023c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        }
7819bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
782b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent intent = getIntent();
783b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bundle myExtras = intent.getExtras();
784b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
7859bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent && myExtras != null) {
786b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
787b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (saveUri != null) {
788b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
789b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCameraVideoFileDescriptor = mContentResolver.
790b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        openFileDescriptor(saveUri, "rw").getFileDescriptor();
791b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCurrentVideoUri = saveUri;
792d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                } catch (java.io.FileNotFoundException ex) {
793b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // invalid uri
794b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.e(TAG, ex.toString());
795b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
796b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
797b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
798b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        releaseMediaRecorder();
799b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
800b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mSurfaceHolder == null) {
801b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "SurfaceHolder is null");
802b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
803b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
804acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang
805acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang        if (!startPreview()) return false;
806acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang
807b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder = new MediaRecorder();
808b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
809845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mMediaRecorder.setCamera(mCameraDevice);
810d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
811b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
812b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
81382ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang        mMediaRecorder.setMaxDuration(mMaxVideoDurationInMs);
8148d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
8159a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (mStorageStatus != STORAGE_STATUS_OK) {
816b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.setOutputFile("/dev/null");
817b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
818d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // We try Uri in intent first. If it doesn't work, use our own
819d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // instead.
820b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCameraVideoFileDescriptor != null) {
821b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOutputFile(mCameraVideoFileDescriptor);
822b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
823b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                createVideoPath();
824b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOutputFile(mCameraVideoFilename);
825b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
826b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
827b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
828b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
829b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // Use the same frame rate for both, since internally
830b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // if the frame rate is too large, it can cause camera to become
831b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // unstable. We need to fix the MediaRecorder to disable the support
832b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // of setting frame rate for now.
833b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoFrameRate(20);
834845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mMediaRecorder.setVideoSize(mVideoWidth, mVideoHeight);
835b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
836d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
837b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
838de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
839de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        long remaining = getAvailableStorage();
840de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        // remaining >= LOW_STORAGE_THRESHOLD at this point, reserve a quarter
841d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // of that to make it more likely that recording can complete
842d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // successfully.
843de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        try {
844d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mMediaRecorder.setMaxFileSize(remaining -
845d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    LOW_STORAGE_THRESHOLD / 4);
846de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        } catch (RuntimeException exception) {
847de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // We are going to ignore failure of setMaxFileSize here, as
848de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // a) The composer selected may simply not support it, or
849de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // b) The underlying media framework may not handle 64-bit range
850de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            //    on the size restriction.
851de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        }
852de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
853b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
854b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.prepare();
855b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (IOException exception) {
856b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "prepare failed for " + mCameraVideoFilename);
857b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            releaseMediaRecorder();
858b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // TODO: add more exception handling logic here
859b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
860b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
861b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorderRecording = false;
8629bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
863ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        // Update the last video thumbnail.
864ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        if (!mIsVideoCaptureIntent
865ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                && !mHandler.hasMessages(UPDATE_LAST_VIDEO)) {
866ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            mHandler.sendEmptyMessage(UPDATE_LAST_VIDEO);
8679bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
868b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
869b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
870b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
871b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void releaseMediaRecorder() {
872b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Releasing media recorder.");
873b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mMediaRecorder != null) {
874b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cleanupEmptyFile();
875b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.reset();
876b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.release();
877b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder = null;
878b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
879b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
880b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
881b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int getIntPreference(String key, int defaultValue) {
882b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String s = mPreferences.getString(key, "");
883b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int result = defaultValue;
884b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
885b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            result = Integer.parseInt(s);
886b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (NumberFormatException e) {
887b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Ignore, result is already the default value.
888b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
889b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return result;
890b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
891b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
892b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean getBooleanPreference(String key, boolean defaultValue) {
893b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return getIntPreference(key, defaultValue ? 1 : 0) != 0;
894b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
895b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
896b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void createVideoPath() {
897b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        long dateTaken = System.currentTimeMillis();
898b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String title = createName(dateTaken);
899b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String displayName = title + ".3gp"; // Used when emailing.
900b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME;
901b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        File cameraDir = new File(cameraDirPath);
902b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        cameraDir.mkdirs();
903b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SimpleDateFormat dateFormat = new SimpleDateFormat(
904b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                getString(R.string.video_file_name_format));
905b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Date date = new Date(dateTaken);
906b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String filepart = dateFormat.format(date);
907b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String filename = cameraDirPath + "/" + filepart + ".3gp";
908b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ContentValues values = new ContentValues(7);
909b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.TITLE, title);
910b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DISPLAY_NAME, displayName);
911b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DATE_TAKEN, dateTaken);
912b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.MIME_TYPE, "video/3gpp");
913b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DATA, filename);
914b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFilename = filename;
915b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Current camera video filename: " + mCameraVideoFilename);
916b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCurrentVideoValues = values;
917b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
918b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
919b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void registerVideo() {
920b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraVideoFileDescriptor == null) {
921b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri videoTable = Uri.parse("content://media/external/video/media");
922b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoUri = mContentResolver.insert(videoTable,
923b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCurrentVideoValues);
924b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "Current video URI: " + mCurrentVideoUri);
925b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
926b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCurrentVideoValues = null;
927b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
928b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
929b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void deleteCurrentVideo() {
930b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCurrentVideoFilename != null) {
931b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            deleteVideoFile(mCurrentVideoFilename);
932b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoFilename = null;
933b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
934b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCurrentVideoUri != null) {
935b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mContentResolver.delete(mCurrentVideoUri, null, null);
936b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoUri = null;
937b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
938de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        updateAndShowStorageHint(true);
939b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
940b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
941b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void deleteVideoFile(String fileName) {
942b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Deleting video " + fileName);
943b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        File f = new File(fileName);
944d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (!f.delete()) {
945b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "Could not delete " + fileName);
946b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
947b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
948b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
949b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void addBaseMenuItems(Menu menu) {
950b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.addSwitchModeMenuItem(menu, this, false);
951b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
952d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.IMAGE_MODE_ITEM,
953d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_GALLERY_PHOTOS, 0, R.string.camera_gallery_photos_text)
954d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
955d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
956d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
957d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
958d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
959d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
960b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
961b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
962b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
963b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
964d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.VIDEO_MODE_ITEM,
965d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_GALLERY_VIDEOS, 0, R.string.camera_gallery_photos_text)
966d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
967d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
968d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
969d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
970d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
971d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
972b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
973b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
974b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
975b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
976d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        MenuItem item = menu.add(MenuHelper.GENERIC_ITEM, MENU_SETTINGS, 0,
977d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                R.string.settings)
978d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                .setOnMenuItemClickListener(new OnMenuItemClickListener() {
979d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    public boolean onMenuItemClick(MenuItem item) {
980d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        Intent intent = new Intent();
981d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        intent.setClass(VideoCamera.this, CameraSettings.class);
982d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        startActivity(intent);
983d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        return true;
984d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    }
985d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                });
986b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        item.setIcon(android.R.drawable.ic_menu_preferences);
987b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
988b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
989b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // from MediaRecorder.OnErrorListener
990b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onError(MediaRecorder mr, int what, int extra) {
991b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) {
992b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // We may have run out of space on the sdcard.
993b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            stopVideoRecording();
9949a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            updateAndShowStorageHint(true);
995b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
996b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
997b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
9988d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    // from MediaRecorder.OnInfoListener
9998d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    public void onInfo(MediaRecorder mr, int what, int extra) {
10008d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
1001de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            mShutterButton.performClick();
1002d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        } else if (what
1003d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
1004de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            mShutterButton.performClick();
1005de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            updateAndShowStorageHint(true);
10068d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        }
10078d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    }
10088d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
10099c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    /*
10109c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     * Make sure we're not recording music playing in the background, ask
10119c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     * the MediaPlaybackService to pause playback.
10129c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     */
10139c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private void pauseAudioPlayback() {
10149c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // Shamelessly copied from MediaPlaybackService.java, which
10159c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // should be public, but isn't.
10169c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        Intent i = new Intent("com.android.music.musicservicecommand");
10179c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        i.putExtra("command", "pause");
10189c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
10199c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        sendBroadcast(i);
10209c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    }
10219c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
1022b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void startVideoRecording() {
1023b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "startVideoRecording");
1024b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (!mMediaRecorderRecording) {
1025b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10269a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            if (mStorageStatus != STORAGE_STATUS_OK) {
1027b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "Storage issue, ignore the start request");
1028b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
1029b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1030b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1031b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Check mMediaRecorder to see whether it is initialized or not.
1032d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            if (mMediaRecorder == null && initializeVideo() == false) {
1033b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Initialize video (MediaRecorder) failed.");
1034b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
1035b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1036b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10379c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            pauseAudioPlayback();
10389c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
1039b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1040b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOnErrorListener(this);
10418d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                mMediaRecorder.setOnInfoListener(this);
1042b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.start();   // Recording is now started
1043b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (RuntimeException e) {
1044b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Could not start media recorder. ", e);
1045b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
1046b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1047b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorderRecording = true;
1048b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingStartTime = SystemClock.uptimeMillis();
1049b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateRecordingIndicator(true);
1050b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setText("");
1051b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setVisibility(View.VISIBLE);
1052b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mHandler.sendEmptyMessage(UPDATE_RECORD_TIME);
1053b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setScreenTimeoutInfinite();
1054ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // Last picture button is hidden. No need to update last video.
1055ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            mHandler.removeMessages(UPDATE_LAST_VIDEO);
1056b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1057b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1058b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1059b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateRecordingIndicator(boolean showRecording) {
1060d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        int drawableId = showRecording
1061059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin                ? R.drawable.ic_camera_indicator_stop
1062d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                : R.drawable.ic_camera_indicator_video;
1063b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Drawable drawable = getResources().getDrawable(drawableId);
1064b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setImageDrawable(drawable);
1065b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1066b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10679bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void stopVideoRecordingAndGetThumbnail() {
10689bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        stopVideoRecording();
10699bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        acquireVideoThumb();
1070b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1071b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1072de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    private void stopVideoRecordingAndShowAlert() {
1073de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        stopVideoRecording();
10749bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        showAlert();
1075de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1076de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
10779bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void showAlert() {
1078059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.review_indicator).setVisibility(View.VISIBLE);
1079059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.video_indicator).setVisibility(View.INVISIBLE);
1080059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin
1081b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] pickIds = {R.id.attach, R.id.cancel};
1082b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] normalIds = {R.id.gallery, R.id.share, R.id.discard};
1083b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] alwaysOnIds = {R.id.play};
1084b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] hideIds = pickIds;
1085b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] connectIds = normalIds;
10869bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent) {
1087b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            hideIds = normalIds;
1088b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            connectIds = pickIds;
1089b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1090d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        for (int id : hideIds) {
1091b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostPictureAlert.findViewById(id).setVisibility(View.GONE);
1092b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
10938d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        ActionMenuButton shareButton =
10948d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                (ActionMenuButton) mPostPictureAlert.findViewById(R.id.share);
10958d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        shareButton.setRestricted(
10968d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                mCurrentVideoFileLength > SHARE_FILE_LENGTH_LIMIT);
1097b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        connectAndFadeIn(connectIds);
1098b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        connectAndFadeIn(alwaysOnIds);
1099b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPostPictureAlert.setVisibility(View.VISIBLE);
1100059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        mVideoPreview.setVisibility(View.INVISIBLE);
11019bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
11029bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // There are two cases we are here:
11039bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // (1) We are in a capture video intent, and we are reviewing the video
1104095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin        //     we just taken.
11059bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // (2) The thumbnail button is clicked: we review the video associated
11069bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        //     with the thumbnail.
11079bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // For the second case, we copy the associated URI and filename to
11089bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // mCurrentVideoUri and mCurrentVideoFilename, so the video frame shown
11099bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // and the target for actions (play, delete, ...) will be correct.
11109bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
11119bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
1112cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync            if (mThumbController.isUriValid()) {
1113cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync                mCurrentVideoUri = mThumbController.getUri();
1114cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync                mCurrentVideoFilename = getDataPath(mCurrentVideoUri);
1115cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync            } else {
1116cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync                return;
1117cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync            }
11189bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
11199bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
11209bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        String path = mCurrentVideoFilename;
11219bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (path != null) {
1122101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            Bitmap videoFrame = Util.createVideoThumbnail(path);
11239bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mVideoFrame.setImageBitmap(videoFrame);
11249bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mVideoFrame.setVisibility(View.VISIBLE);
11259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
1126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1127b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11289bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlert() {
1129059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        mVideoPreview.setVisibility(View.VISIBLE);
1130de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mVideoFrame.setVisibility(View.INVISIBLE);
1131de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mPostPictureAlert.setVisibility(View.INVISIBLE);
1132de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        showLastPictureButton();
1133de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1134de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
1135b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void connectAndFadeIn(int[] connectIds) {
1136d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        for (int id : connectIds) {
1137b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            View view = mPostPictureAlert.findViewById(id);
1138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            view.setOnClickListener(this);
1139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Animation animation = new AlphaAnimation(0F, 1F);
1140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            animation.setDuration(500);
11419bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            view.startAnimation(animation);
1142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private boolean isAlertVisible() {
1146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return mPostPictureAlert.getVisibility() == View.VISIBLE;
1147b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void stopVideoRecording() {
1150b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "stopVideoRecording");
1151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean needToRegisterRecording = false;
1152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mMediaRecorderRecording || mMediaRecorder != null) {
1153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mMediaRecorderRecording && mMediaRecorder != null) {
1154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
1155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mMediaRecorder.setOnErrorListener(null);
11568d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    mMediaRecorder.setOnInfoListener(null);
1157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mMediaRecorder.stop();
1158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } catch (RuntimeException e) {
1159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.e(TAG, "stop fail: " + e.getMessage());
1160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
11618d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
1162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCurrentVideoFilename = mCameraVideoFilename;
11638d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                try {
1164d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    mCurrentVideoFileLength =
1165d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            new File(mCurrentVideoFilename).length();
11668d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                } catch (RuntimeException e) {
11678d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    Log.e(TAG, "get file length fail: " + e.getMessage());
11688d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    mCurrentVideoFileLength = 0;
11698d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                }
1170d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Log.v(TAG, "Setting current video filename: "
1171d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        + mCurrentVideoFilename);
1172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                needToRegisterRecording = true;
1173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorderRecording = false;
1174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            releaseMediaRecorder();
1176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateRecordingIndicator(false);
1177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setVisibility(View.GONE);
1178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setScreenTimeoutLong();
1179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
11809a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (needToRegisterRecording && mStorageStatus == STORAGE_STATUS_OK) {
11819a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            registerVideo();
11829a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
1183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFilename = null;
1185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFileDescriptor = null;
1186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1187b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutSystemDefault() {
1189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        clearScreenOnFlag();
1191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1193b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutLong() {
1194b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenOnFlag();
1196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
1197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutInfinite() {
1200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1201b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenOnFlag();
1202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1203b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void clearScreenOnFlag() {
1205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window w = getWindow();
1206d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1207d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if ((w.getAttributes().flags & flag) != 0) {
1208d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            w.clearFlags(flag);
1209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1210b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenOnFlag() {
1213b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window w = getWindow();
1214d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1215d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if ((w.getAttributes().flags & flag) == 0) {
1216d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            w.addFlags(flag);
1217b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1218b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1219b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12209bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlertAndStartPreview() {
12219bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlert();
12229bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        initializeVideo();
1223b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlertAndStartVideoRecording() {
12269bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlert();
12279bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        startVideoRecording();
1228b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1229b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12309bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void acquireVideoThumb() {
1231101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        Bitmap videoFrame = Util.createVideoThumbnail(mCurrentVideoFilename);
12329bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mThumbController.setData(mCurrentVideoUri, videoFrame);
1233de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1234de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void showLastPictureButton() {
12369bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
12379bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setVisibility(View.VISIBLE);
1238de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        }
12399bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    }
1240de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12419bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static ImageManager.DataLocation dataLocation() {
12429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        return ImageManager.DataLocation.EXTERNAL;
1243de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1244de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void updateLastVideo() {
124658e94eddd371a9bb7c04936dbeb99615fd1a0c2cChih-Chung Chang        IImageList list = ImageManager.allImages(
12479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mContentResolver,
12489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            dataLocation(),
12499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.INCLUDE_VIDEOS,
12509bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.SORT_ASCENDING,
12519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.CAMERA_IMAGE_BUCKET_ID);
12529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        int count = list.getCount();
12539bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (count > 0) {
1254d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            IImage image = list.getImageAt(count - 1);
12559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            Uri uri = image.fullSizeImageUri();
12569bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(uri, image.miniThumbBitmap());
12579bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } else {
12589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(null, null);
12599bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
12609bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        list.deactivate();
1261b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1262b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12639bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static final String[] DATA_PATH_PROJECTION = new String[] {
12649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        "_data"
12659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    };
12669bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
12679bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private String getDataPath(Uri uri) {
12689bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        Cursor c = null;
12699bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        try {
1270d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            c = mContentResolver.query(uri, DATA_PATH_PROJECTION, null, null,
1271d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    null);
12729bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (c != null && c.moveToFirst()) {
12739bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                return c.getString(0);
12749bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            } else {
12759bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                return null;
12769bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            }
12779bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } finally {
127823c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            if (c != null) {
127923c51b794e95c201290e36737f379c4bb8eefeaeRay Chen                c.close();
128023c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            }
1281b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1282b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1283d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1284d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private void updateRecordingTime() {
128523c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        if (!mMediaRecorderRecording) {
128623c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            return;
128723c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        }
1288d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long now = SystemClock.uptimeMillis();
1289d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long delta = now - mRecordingStartTime;
1290d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1291d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // Starting a minute before reaching the max duration
1292d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // limit, we'll countdown the remaining time instead.
1293d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        boolean countdownRemainingTime =
129482ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang            (delta >= mMaxVideoDurationInMs - 60000);
1295d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1296d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (countdownRemainingTime) {
129782ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang            delta = Math.max(0, mMaxVideoDurationInMs - delta);
1298d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1299d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1300d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long seconds = (delta + 500) / 1000;  // round to nearest
1301d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long minutes = seconds / 60;
1302d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long hours = minutes / 60;
1303d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long remainderMinutes = minutes - (hours * 60);
1304d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long remainderSeconds = seconds - (minutes * 60);
1305d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1306d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String secondsString = Long.toString(remainderSeconds);
1307d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (secondsString.length() < 2) {
1308d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            secondsString = "0" + secondsString;
1309d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1310d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String minutesString = Long.toString(remainderMinutes);
1311d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (minutesString.length() < 2) {
1312d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            minutesString = "0" + minutesString;
1313d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1314d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String text = minutesString + ":" + secondsString;
1315d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (hours > 0) {
1316d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            String hoursString = Long.toString(hours);
1317d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            if (hoursString.length() < 2) {
1318d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                hoursString = "0" + hoursString;
1319d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            }
1320d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            text = hoursString + ":" + text;
1321d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1322d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mRecordingTimeView.setText(text);
1323d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1324d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (mRecordingTimeCountsDown != countdownRemainingTime) {
1325d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // Avoid setting the color on every update, do it only
1326d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // when it needs changing.
1327d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1328d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mRecordingTimeCountsDown = countdownRemainingTime;
1329d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1330d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int color = getResources().getColor(
1331d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    countdownRemainingTime
1332d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    ? R.color.recording_time_remaining_text
1333d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    : R.color.recording_time_elapsed_text);
1334d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1335d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mRecordingTimeView.setTextColor(color);
1336d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1337d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1338d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // Work around a limitation of the T-Mobile G1: The T-Mobile
1339d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // hardware blitter can't pixel-accurately scale and clip at the
1340d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // same time, and the SurfaceFlinger doesn't attempt to work around
1341d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // this limitation. In order to avoid visual corruption we must
1342d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // manually refresh the entire surface view when changing any
1343d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // overlapping view's contents.
1344d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mVideoPreview.invalidate();
1345d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mHandler.sendEmptyMessageDelayed(UPDATE_RECORD_TIME, 1000);
1346d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    }
1347b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project}
1348