VideoCamera.java revision cd65be31531717fb032b7423f8d5a77df465cfca
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
76b128446b7ef264c33e91e119391045156a19439bWu-cheng Li    private static final int INIT_RECORDER = 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;
85b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private static final int STORAGE_STATUS_OK = 0;
879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private static final int STORAGE_STATUS_LOW = 1;
889a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private static final int STORAGE_STATUS_NONE = 2;
899a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
90b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SETTINGS = 6;
91b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_PHOTOS = 7;
92b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_VIDEOS = 8;
93b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_GALLERY_PHOTO = 34;
94b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_PLAY_VIDEO = 35;
95b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_SELECT_VIDEO = 36;
96b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_NEW_VIDEO = 37;
97b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
98b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    SharedPreferences mPreferences;
99b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final float VIDEO_ASPECT_RATIO = 176.0f / 144.0f;
101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    VideoPreview mVideoPreview;
102b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    SurfaceHolder mSurfaceHolder = null;
103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    ImageView mVideoFrame;
1049bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
1059bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private boolean mIsVideoCaptureIntent;
1069bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // mLastPictureButton and mThumbController
1070a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang    // are non-null only if mIsVideoCaptureIntent is true.
108de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    private ImageView mLastPictureButton;
1099bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private ThumbnailController mThumbController;
110b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1119a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private int mStorageStatus = STORAGE_STATUS_OK;
1129a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
113b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private MediaRecorder mMediaRecorder;
114b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mMediaRecorderRecording = false;
115b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mRecordingStartTime;
116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // The video file that the hardware camera is about to record into
117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // (or is recording into.)
118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private String mCameraVideoFilename;
119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private FileDescriptor mCameraVideoFileDescriptor;
120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // The video file that has already been recorded, and that is being
122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // examined by the user.
123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private String mCurrentVideoFilename;
124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Uri mCurrentVideoUri;
125b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ContentValues mCurrentVideoValues;
126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
127845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    // The video frame size we will record (like 352x288).
128845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private int mVideoWidth, mVideoHeight;
129845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
13082ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang    // The video duration limit.
13182ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang    private int mMaxVideoDurationInMs;
13282ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang
133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    boolean mPausing = false;
134ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li    boolean mPreviewing = false;  // True if preview is started.
135b128446b7ef264c33e91e119391045156a19439bWu-cheng Li    boolean mRecorderInitialized = false;
136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
137d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private ContentResolver mContentResolver;
138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ShutterButton mShutterButton;
140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private TextView mRecordingTimeView;
1418d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    private boolean mRecordingTimeCountsDown = false;
142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    ArrayList<MenuItem> mGalleryItems = new ArrayList<MenuItem>();
144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    View mPostPictureAlert;
146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
147059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin    private final Handler mHandler = new MainHandler();
148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
149d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    // This Handler is used to post message back onto the main thread of the
150d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    // application
151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class MainHandler extends Handler {
152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void handleMessage(Message msg) {
154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            switch (msg.what) {
155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case CLEAR_SCREEN_DELAY: {
157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    clearScreenOnFlag();
158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case UPDATE_RECORD_TIME: {
162d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    updateRecordingTime();
163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
166b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                case INIT_RECORDER: {
167b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                    initializeRecorder();
168ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                    break;
169ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                }
170ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                default:
172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.v(TAG, "Unhandled message: " + msg.what);
1730a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang                    break;
174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
176937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Lin    }
177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onReceive(Context context, Intent intent) {
181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            String action = intent.getAction();
182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (action.equals(Intent.ACTION_MEDIA_EJECT)) {
1839a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(false);
184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                stopVideoRecording();
185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
1869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(true);
187b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                mRecorderInitialized = false;
188b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                initializeRecorder();
189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // SD card unavailable
1919a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                // handled in ACTION_MEDIA_EJECT
192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) {
193d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Toast.makeText(VideoCamera.this,
194d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        getResources().getString(R.string.wait), 5000);
195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) {
1969a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(true);
197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
201d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private static String createName(long dateTaken) {
202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString();
203b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /** Called with the activity is first created. */
206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
207b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onCreate(Bundle icicle) {
208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreate(icicle);
209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
210ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        /*
211ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         * To reduce startup time, we open camera device in another thread.
212ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         * Camera is opened in onCreate instead of onResume because there are
213ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         * lots of things to do here and camera open can be done in parallel.
214ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         * We will make sure the camera is opened at the end of onCreate.
215ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li         */
216ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        Thread openCameraThread = new Thread(new Runnable() {
217ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            public void run() {
218cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang                mCameraDevice = CameraHolder.instance().open();
219ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            }
220ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        });
221ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        openCameraThread.start();
222ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
223b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mContentResolver = getContentResolver();
225b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
226b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        requestWindowFeature(Window.FEATURE_PROGRESS);
227b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setContentView(R.layout.video_camera);
228b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
229b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoPreview = (VideoPreview) findViewById(R.id.camera_preview);
230b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoPreview.setAspectRatio(VIDEO_ASPECT_RATIO);
231b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
232b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // don't set mSurfaceHolder here. We have it set ONLY within
233b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // surfaceCreated / surfaceDestroyed, other parts of the code
234b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // assume that when it is set, the surface is also set.
235b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SurfaceHolder holder = mVideoPreview.getHolder();
236b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.addCallback(this);
237b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
238b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
239b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPostPictureAlert = findViewById(R.id.post_picture_panel);
240b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
241b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] ids = new int[]{R.id.play, R.id.share, R.id.discard,
242b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                R.id.cancel, R.id.attach};
243b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int id : ids) {
244b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            findViewById(id).setOnClickListener(this);
245b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
246b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
247059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.video_indicator).setVisibility(View.VISIBLE);
248059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        mShutterButton = (ShutterButton) findViewById(R.id.video_button);
249b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setOnShutterButtonListener(this);
250059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        mShutterButton.requestFocus();
251059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin
252b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mRecordingTimeView = (TextView) findViewById(R.id.recording_time);
253b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoFrame = (ImageView) findViewById(R.id.video_frame);
2549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mIsVideoCaptureIntent = isVideoCaptureIntent();
2559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
256059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            mLastPictureButton = (ImageView) findViewById(R.id.review_button);
2579bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setOnClickListener(this);
258059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            mThumbController = new ThumbnailController(
259059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin                    mLastPictureButton, mContentResolver);
2609bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.loadData(ImageManager.getLastVideoThumbPath());
261059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            findViewById(R.id.camera_button).setOnClickListener(this);
262059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        } else {
263059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            findViewById(R.id.camera_button).setVisibility(View.INVISIBLE);
264059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            findViewById(R.id.review_button).setVisibility(View.INVISIBLE);
2659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
266ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
267ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        // Make sure the camera is opened.
268ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        try {
269ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            openCameraThread.join();
270ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        } catch (InterruptedException ex) {
271ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // ignore
272ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        }
273b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
274b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
275e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    private void startShareVideoActivity() {
276e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        Intent intent = new Intent();
277e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.setAction(Intent.ACTION_SEND);
278e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.setType("video/3gpp");
279e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.putExtra(Intent.EXTRA_STREAM, mCurrentVideoUri);
280e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        try {
281d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            startActivity(Intent.createChooser(
282d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    intent, getText(R.string.sendVideo)));
283e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        } catch (android.content.ActivityNotFoundException ex) {
284d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            Toast.makeText(VideoCamera.this, R.string.no_way_to_share_video,
285d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    Toast.LENGTH_SHORT).show();
286e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
287e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    }
288e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project
289b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onClick(View v) {
290b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (v.getId()) {
291059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            case R.id.camera_button:
292059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin                MenuHelper.gotoCameraMode(this);
293059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin                break;
294b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.gallery:
2950a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang                gotoGallery();
296b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
297b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.attach:
298b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doReturnToCaller(true);
299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
300b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.cancel:
301b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doReturnToCaller(false);
302b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
303b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.discard: {
3047638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                Runnable deleteCallback = new Runnable() {
3057638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                    public void run() {
306b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                        discardCurrentVideoAndInitRecorder();
3077638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                    }
3087638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                };
3097638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                MenuHelper.deleteVideo(this, deleteCallback);
310b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
311b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
312b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.share: {
313e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                startShareVideoActivity();
314b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
315b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
316b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.play: {
317b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doPlayCurrentVideo();
318b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
319b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
320059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            case R.id.review_button: {
3219bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndShowAlert();
322de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                break;
323de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            }
324b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
325b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
326b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
327b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onShutterButtonFocus(ShutterButton button, boolean pressed) {
328de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        // Do nothing (everything happens in onShutterButtonClick).
329de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
330de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
331de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    public void onShutterButtonClick(ShutterButton button) {
332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (button.getId()) {
333059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            case R.id.video_button:
334de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                if (mMediaRecorderRecording) {
3359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    if (mIsVideoCaptureIntent) {
336de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                        stopVideoRecordingAndShowAlert();
337b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } else {
3389bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        stopVideoRecordingAndGetThumbnail();
339b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                        mRecorderInitialized = false;
340b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                        initializeRecorder();
3419bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    }
3429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                } else if (isAlertVisible()) {
3439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    if (mIsVideoCaptureIntent) {
344b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                        discardCurrentVideoAndInitRecorder();
3459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    } else {
346b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                        hideAlertAndInitializeRecorder();
347b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
348b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                } else if (mRecorderInitialized) {
349b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                    // If the click comes before recorder initialization, it is
350b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                    // ignored. If users click the button during initialization,
351b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                    // the event is put in the queue and record will be started
352b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                    // eventually.
353de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    startVideoRecording();
354b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
355b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
356b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
357b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
358b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
359b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doPlayCurrentVideo() {
3600a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang        Log.v(TAG, "Playing current video: " + mCurrentVideoUri);
361b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri);
362b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
363b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            startActivity(intent);
364b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (android.content.ActivityNotFoundException ex) {
365b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex);
366b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
367b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
368b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
369b128446b7ef264c33e91e119391045156a19439bWu-cheng Li    private void discardCurrentVideoAndInitRecorder() {
370b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        deleteCurrentVideo();
371b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        hideAlertAndInitializeRecorder();
372b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
373b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
374b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private OnScreenHint mStorageHint;
375b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3769a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private void updateAndShowStorageHint(boolean mayHaveSd) {
3779a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mStorageStatus = getStorageStatus(mayHaveSd);
3789a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        showStorageHint();
3799a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    }
3809a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
3819a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private void showStorageHint() {
382b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String errorMessage = null;
3839a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        switch (mStorageStatus) {
3849a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        case STORAGE_STATUS_NONE:
385b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            errorMessage = getString(R.string.no_storage);
3869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            break;
3879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        case STORAGE_STATUS_LOW:
388b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            errorMessage = getString(R.string.spaceIsLow_content);
389b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
390b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (errorMessage != null) {
391b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStorageHint == null) {
392b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint = OnScreenHint.makeText(this, errorMessage);
393b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
394b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint.setText(errorMessage);
395b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.show();
397b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else if (mStorageHint != null) {
398b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
399b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
400b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
401b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
402b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4039a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private int getStorageStatus(boolean mayHaveSd) {
4049a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        long remaining = mayHaveSd ? getAvailableStorage() : NO_STORAGE_ERROR;
4059a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (remaining == NO_STORAGE_ERROR) {
4069a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            return STORAGE_STATUS_NONE;
4079a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
4089a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        return remaining < LOW_STORAGE_THRESHOLD
4099a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                ? STORAGE_STATUS_LOW : STORAGE_STATUS_OK;
4109a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    }
4119a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
412845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private void readVideoSizePreference() {
413845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        boolean videoQualityHigh = getBooleanPreference(
414845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang                CameraSettings.KEY_VIDEO_QUALITY,
415845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang                CameraSettings.DEFAULT_VIDEO_QUALITY_VALUE);
416845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
41782ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang        // 1 minute = 60000ms
41882ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang        mMaxVideoDurationInMs = 60000 * getIntPreference(
41982ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang                CameraSettings.KEY_VIDEO_DURATION,
42082ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang                CameraSettings.DEFAULT_VIDEO_DURATION_VALUE);
42182ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang
422845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        Intent intent = getIntent();
423845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) {
424845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            int extraVideoQuality = intent.getIntExtra(
425845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang                    MediaStore.EXTRA_VIDEO_QUALITY, 0);
426845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            videoQualityHigh = (extraVideoQuality > 0);
427845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
428845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
429845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        if (videoQualityHigh) {
430845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            // CIF size
431845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoWidth = 352;
432845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoHeight = 288;
433845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        } else {
434845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            // QCIF size
435845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoWidth = 176;
436845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoHeight = 144;
437845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
438845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
439845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
440b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
441b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onResume() {
442b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onResume();
443845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mPausing = false;
444b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
445b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutLong();
446845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        readVideoSizePreference();
447b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
448b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // install an intent filter to receive SD card related events.
449d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        IntentFilter intentFilter =
450d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_EJECT);
452b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
453b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
454b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
455b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addDataScheme("file");
456b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        registerReceiver(mReceiver, intentFilter);
4579a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mStorageStatus = getStorageStatus(true);
4589a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
4599a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mHandler.postDelayed(new Runnable() {
4609a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            public void run() {
4619a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                showStorageHint();
4629a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            }
4639a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }, 200);
464b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
465b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        if (mSurfaceHolder != null) {
466b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            startPreview();
467b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            mRecorderInitialized = false;
468b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            mHandler.sendEmptyMessage(INIT_RECORDER);
469b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        }
470b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
471b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
472845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private void setCameraParameters() {
473845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        android.hardware.Camera.Parameters param;
474845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        param = mCameraDevice.getParameters();
475845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        param.setPreviewSize(mVideoWidth, mVideoHeight);
476845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice.setParameters(param);
477845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
478845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
479845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    // Precondition: mSurfaceHolder != null
480acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang    // Returns true if starting preview succeeds.
481acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang    private boolean startPreview() {
482059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.review_indicator).setVisibility(View.INVISIBLE);
483059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.video_indicator).setVisibility(View.VISIBLE);
484059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin
485845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        Log.v(TAG, "startPreview");
486ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        if (mPreviewing) {
4871fb8ac4e3e03f31e6e099776d1026b9cadf57610Chih-Chung Chang            // After recording a video, preview is not stopped. So just return.
488acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang            return true;
489845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
490ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
491ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        if (mCameraDevice == null) {
492ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // If the activity is paused and resumed, camera device has been
493ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // released and we need to open the camera.
494cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang            mCameraDevice = CameraHolder.instance().open();
495ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        }
496ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
497845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        setCameraParameters();
498845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        try {
499845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.setPreviewDisplay(mSurfaceHolder);
500845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        } catch (IOException ex) {
501cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang            CameraHolder.instance().release();
502845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice = null;
503845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            Log.e(TAG, "failed to set preview display");
504acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang            return false;
505845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
506ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
507845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        try {
508845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.startPreview();
509ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            mPreviewing = true;
510845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        } catch (Throwable ex) {
511845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            // TODO: change Throwable to IOException once
512845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            //      android.hardware.Camera.startPreview properly declares
513845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            //      that it throws IOException.
514cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang            CameraHolder.instance().release();
515845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice = null;
516845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            Log.e(TAG, "failed to start preview");
517acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang            return false;
518845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
519845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice.unlock();
520acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang        return true;
521845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
522845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
523d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang    private void closeCamera() {
524d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang        Log.v(TAG, "closeCamera");
525845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        if (mCameraDevice == null) {
526845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            Log.d(TAG, "already stopped.");
527845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            return;
528845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
529fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        // If we don't lock the camera, release() will fail.
530fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        mCameraDevice.lock();
531cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang        CameraHolder.instance().release();
532845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice = null;
533ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        mPreviewing = false;
534845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
535845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
536b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
537b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onStop() {
538b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutSystemDefault();
539b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onStop();
540b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
541b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
542b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
543b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    protected void onPause() {
544b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPause();
545b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
546fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        mPausing = true;
547fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li
5489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // This is similar to what mShutterButton.performClick() does,
5499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // but not quite the same.
5509bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mMediaRecorderRecording) {
5519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (mIsVideoCaptureIntent) {
5529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndShowAlert();
5539bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            } else {
5549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndGetThumbnail();
5559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            }
5569bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } else {
5579bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            stopVideoRecording();
5589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
559fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        closeCamera();
560b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5619c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        unregisterReceiver(mReceiver);
562b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutSystemDefault();
563b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
5659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.storeData(ImageManager.getLastVideoThumbPath());
5669bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
567095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin
568b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mStorageHint != null) {
569b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
570b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
571b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
572845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
573b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        mHandler.removeMessages(INIT_RECORDER);
574b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
575b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
576b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
577b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
578fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        // Do not handle any key if the activity is paused.
579fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        if (mPausing) {
580fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li            return true;
581fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        }
582fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li
583b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutLong();
584b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
585b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (keyCode) {
586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_BACK:
587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mMediaRecorderRecording) {
588de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
590d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                } else if (isAlertVisible()) {
591b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                    hideAlertAndInitializeRecorder();
592b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
593b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
594b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_CAMERA:
596b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
597de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
600de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                break;
601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_CENTER:
602b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
603de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
604de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    return true;
605b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
606b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
607b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_MENU:
608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mMediaRecorderRecording) {
609de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
610b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
611b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
612b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
613b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
614b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
615b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyDown(keyCode, event);
616b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
617b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
618b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
619b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
620b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch(keyCode) {
621b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case KeyEvent.KEYCODE_CAMERA:
622b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mShutterButton.setPressed(false);
623b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return true;
624b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
625b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyUp(keyCode, event);
626b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
628b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
629314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber        if (mPausing) {
630314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // We're pausing, the screen is off and we already stopped
631314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // video recording. We don't want to start the camera again
632314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // in this case in order to conserve power.
633314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // The fact that surfaceChanged is called _after_ an onPause appears
634314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // to be legitimate since in that case the lockscreen always returns
635314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // to portrait orientation possibly triggering the notification.
636314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            return;
637314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber        }
638314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber
639b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        if (mMediaRecorderRecording) {
640b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            stopVideoRecording();
641b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        }
642b128446b7ef264c33e91e119391045156a19439bWu-cheng Li
643b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        // Start the preview if it is not started yet. Preview may be already
644b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        // started in onResume and then surfaceChanged is called due to
645b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        // orientation change.
646b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        if (!mPreviewing) {
647b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            startPreview();
648b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            mRecorderInitialized = false;
649b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            mHandler.sendEmptyMessage(INIT_RECORDER);
650b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        }
651b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
652b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
653b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceCreated(SurfaceHolder holder) {
654b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = holder;
655b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
656b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
657b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceDestroyed(SurfaceHolder holder) {
658b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = null;
659b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
660b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6610a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang    private void gotoGallery() {
662b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.gotoCameraVideoGallery(this);
663b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
665b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
666b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onPrepareOptionsMenu(Menu menu) {
667b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPrepareOptionsMenu(menu);
668b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int i = 1; i <= MenuHelper.MENU_ITEM_MAX; i++) {
670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (i != MenuHelper.GENERIC_ITEM) {
671b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                menu.setGroupVisible(i, false);
672b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
673b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
674b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
675b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        menu.setGroupVisible(MenuHelper.VIDEO_MODE_ITEM, true);
676b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
677b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
678b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
679b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
680b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onCreateOptionsMenu(Menu menu) {
681b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreateOptionsMenu(menu);
682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6839bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent) {
684b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // No options menu for attach mode.
685b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
686b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
687b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            addBaseMenuItems(menu);
688d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int menuFlags = MenuHelper.INCLUDE_ALL
689d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    & ~MenuHelper.INCLUDE_ROTATE_MENU
690095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin                    & ~MenuHelper.INCLUDE_DETAILS_MENU;
691b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            MenuHelper.addImageMenuItems(
692b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    menu,
693095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin                    menuFlags,
694b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    false,
695b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    VideoCamera.this,
69623c51b794e95c201290e36737f379c4bb8eefeaeRay Chen                    mHandler,
697b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // Handler for deletion
698b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    new Runnable() {
699b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run() {
700b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            // What do we do here?
701b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            // mContentResolver.delete(uri, null, null);
702b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
703b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    },
704b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    new MenuHelper.MenuInvoker() {
705b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run(final MenuHelper.MenuCallback cb) {
706b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
707b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    });
708b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
709d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.IMAGE_SAVING_ITEM,
710d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_SAVE_GALLERY_PHOTO, 0,
711d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    R.string.camera_gallery_photos_text)
712d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(
713d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    new MenuItem.OnMenuItemClickListener() {
714d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
715d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
716d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
717d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
718d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
719b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
720b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
721b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
722b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
723b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
724b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean isVideoCaptureIntent() {
725b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String action = getIntent().getAction();
726b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action));
727b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
728b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
729b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doReturnToCaller(boolean success) {
730b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent resultIntent = new Intent();
731b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int resultCode;
732b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (success) {
733b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultCode = RESULT_OK;
734b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultIntent.setData(mCurrentVideoUri);
735b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
736b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultCode = RESULT_CANCELED;
737b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
738b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setResult(resultCode, resultIntent);
739b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        finish();
740b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
741b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
742b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
743b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * Returns
744b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * @return number of bytes available, or an ERROR code.
745b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
746b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static long getAvailableStorage() {
747b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
748b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (!ImageManager.hasStorage()) {
749b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return NO_STORAGE_ERROR;
750b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
751d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                String storageDirectory = Environment
752d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        .getExternalStorageDirectory().toString();
753b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                StatFs stat = new StatFs(storageDirectory);
754d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                return ((long) stat.getAvailableBlocks()
755d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        * (long) stat.getBlockSize());
756b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
75723c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        } catch (RuntimeException ex) {
758b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // if we can't stat the filesystem then we don't know how many
759b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // free bytes exist.  It might be zero but just leave it
760b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // blank since we really don't know.
761b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return CANNOT_STAT_ERROR;
762b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
763b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
764b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
765b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void cleanupEmptyFile() {
766b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraVideoFilename != null) {
767b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            File f = new File(mCameraVideoFilename);
768b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (f.length() == 0 && f.delete()) {
769b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project              Log.v(TAG, "Empty video file deleted: " + mCameraVideoFilename);
770b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project              mCameraVideoFilename = null;
771b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
772b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
773b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
774b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
775845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private android.hardware.Camera mCameraDevice;
776b128446b7ef264c33e91e119391045156a19439bWu-cheng Li    // initializeRecorder() prepares media recorder. Return false if fails.
777b128446b7ef264c33e91e119391045156a19439bWu-cheng Li    private boolean initializeRecorder() {
778b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        Log.v(TAG, "initializeRecorder");
779b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        if (mRecorderInitialized) return true;
7809bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
781b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        // We will call initializeRecorder() again when the alert is hidden.
78223c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        if (isAlertVisible()) {
78323c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            return false;
78423c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        }
7859bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
786b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent intent = getIntent();
787b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bundle myExtras = intent.getExtras();
788b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
7899bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent && myExtras != null) {
790b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
791b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (saveUri != null) {
792b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
793b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCameraVideoFileDescriptor = mContentResolver.
794b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        openFileDescriptor(saveUri, "rw").getFileDescriptor();
795b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCurrentVideoUri = saveUri;
796d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                } catch (java.io.FileNotFoundException ex) {
797b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // invalid uri
798b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.e(TAG, ex.toString());
799b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
800b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
801b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
802b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        releaseMediaRecorder();
803b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
804b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder = new MediaRecorder();
805b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
806845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mMediaRecorder.setCamera(mCameraDevice);
807d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
808b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
809b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
81082ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang        mMediaRecorder.setMaxDuration(mMaxVideoDurationInMs);
8118d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
8129a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (mStorageStatus != STORAGE_STATUS_OK) {
813b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.setOutputFile("/dev/null");
814b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
815d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // We try Uri in intent first. If it doesn't work, use our own
816d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // instead.
817b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCameraVideoFileDescriptor != null) {
818b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOutputFile(mCameraVideoFileDescriptor);
819b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
820b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                createVideoPath();
821b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOutputFile(mCameraVideoFilename);
822b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
823b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
824b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
825b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // Use the same frame rate for both, since internally
826b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // if the frame rate is too large, it can cause camera to become
827b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // unstable. We need to fix the MediaRecorder to disable the support
828b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // of setting frame rate for now.
829b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoFrameRate(20);
830845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mMediaRecorder.setVideoSize(mVideoWidth, mVideoHeight);
831b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
832d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
833b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
834de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
835de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        long remaining = getAvailableStorage();
836de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        // remaining >= LOW_STORAGE_THRESHOLD at this point, reserve a quarter
837d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // of that to make it more likely that recording can complete
838d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // successfully.
839de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        try {
840d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mMediaRecorder.setMaxFileSize(remaining -
841d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    LOW_STORAGE_THRESHOLD / 4);
842de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        } catch (RuntimeException exception) {
843de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // We are going to ignore failure of setMaxFileSize here, as
844de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // a) The composer selected may simply not support it, or
845de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // b) The underlying media framework may not handle 64-bit range
846de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            //    on the size restriction.
847de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        }
848de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
849b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
850b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.prepare();
851b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (IOException exception) {
852b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "prepare failed for " + mCameraVideoFilename);
853b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            releaseMediaRecorder();
854b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // TODO: add more exception handling logic here
855b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
856b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
857b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorderRecording = false;
8589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
859ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        // Update the last video thumbnail.
860b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        if (!mIsVideoCaptureIntent) {
861b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            if (!mThumbController.isUriValid()) {
862b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                updateLastVideo();
863b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            }
864b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            mThumbController.updateDisplayIfNeeded();
8659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
866b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        mRecorderInitialized = true;
867b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
868b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
869b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
870b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void releaseMediaRecorder() {
871b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Releasing media recorder.");
872b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mMediaRecorder != null) {
873b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cleanupEmptyFile();
874b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.reset();
875b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.release();
876b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder = null;
877b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
878b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
879b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
880b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int getIntPreference(String key, int defaultValue) {
881b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String s = mPreferences.getString(key, "");
882b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int result = defaultValue;
883b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
884b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            result = Integer.parseInt(s);
885b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (NumberFormatException e) {
886b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Ignore, result is already the default value.
887b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
888b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return result;
889b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
890b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
891b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean getBooleanPreference(String key, boolean defaultValue) {
892b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return getIntPreference(key, defaultValue ? 1 : 0) != 0;
893b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
894b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
895b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void createVideoPath() {
896b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        long dateTaken = System.currentTimeMillis();
897b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String title = createName(dateTaken);
898b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String displayName = title + ".3gp"; // Used when emailing.
899b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME;
900b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        File cameraDir = new File(cameraDirPath);
901b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        cameraDir.mkdirs();
902b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SimpleDateFormat dateFormat = new SimpleDateFormat(
903b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                getString(R.string.video_file_name_format));
904b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Date date = new Date(dateTaken);
905b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String filepart = dateFormat.format(date);
906b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String filename = cameraDirPath + "/" + filepart + ".3gp";
907b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ContentValues values = new ContentValues(7);
908b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.TITLE, title);
909b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DISPLAY_NAME, displayName);
910b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DATE_TAKEN, dateTaken);
911b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.MIME_TYPE, "video/3gpp");
912b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DATA, filename);
913b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFilename = filename;
914b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Current camera video filename: " + mCameraVideoFilename);
915b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCurrentVideoValues = values;
916b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
917b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
918b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void registerVideo() {
919b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraVideoFileDescriptor == null) {
920b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri videoTable = Uri.parse("content://media/external/video/media");
921b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoUri = mContentResolver.insert(videoTable,
922b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCurrentVideoValues);
923b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "Current video URI: " + mCurrentVideoUri);
924b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
925b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCurrentVideoValues = null;
926b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
927b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
928b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void deleteCurrentVideo() {
929b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCurrentVideoFilename != null) {
930b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            deleteVideoFile(mCurrentVideoFilename);
931b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoFilename = null;
932b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
933b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCurrentVideoUri != null) {
934b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mContentResolver.delete(mCurrentVideoUri, null, null);
935b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoUri = null;
936b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
937de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        updateAndShowStorageHint(true);
938b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
939b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
940b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void deleteVideoFile(String fileName) {
941b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Deleting video " + fileName);
942b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        File f = new File(fileName);
943d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (!f.delete()) {
944b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "Could not delete " + fileName);
945b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
946b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
947b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
948b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void addBaseMenuItems(Menu menu) {
949b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.addSwitchModeMenuItem(menu, this, false);
950b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
951d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.IMAGE_MODE_ITEM,
952d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_GALLERY_PHOTOS, 0, R.string.camera_gallery_photos_text)
953d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
954d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
955d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
956d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
957d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
958d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
959b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
960b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
961b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
962b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
963d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.VIDEO_MODE_ITEM,
964d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_GALLERY_VIDEOS, 0, R.string.camera_gallery_photos_text)
965d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
966d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
967d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
968d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
969d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
970d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
971b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
972b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
973b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
974b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
975d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        MenuItem item = menu.add(MenuHelper.GENERIC_ITEM, MENU_SETTINGS, 0,
976d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                R.string.settings)
977d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                .setOnMenuItemClickListener(new OnMenuItemClickListener() {
978d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    public boolean onMenuItemClick(MenuItem item) {
979d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        Intent intent = new Intent();
980d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        intent.setClass(VideoCamera.this, CameraSettings.class);
981d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        startActivity(intent);
982d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        return true;
983d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    }
984d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                });
985b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        item.setIcon(android.R.drawable.ic_menu_preferences);
986b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
987b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
988b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // from MediaRecorder.OnErrorListener
989b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onError(MediaRecorder mr, int what, int extra) {
990b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) {
991b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // We may have run out of space on the sdcard.
992b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            stopVideoRecording();
9939a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            updateAndShowStorageHint(true);
994b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
995b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
996b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
9978d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    // from MediaRecorder.OnInfoListener
9988d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    public void onInfo(MediaRecorder mr, int what, int extra) {
9998d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
1000de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            mShutterButton.performClick();
1001d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        } else if (what
1002d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
1003de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            mShutterButton.performClick();
1004de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            updateAndShowStorageHint(true);
10058d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        }
10068d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    }
10078d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
10089c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    /*
10099c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     * Make sure we're not recording music playing in the background, ask
10109c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     * the MediaPlaybackService to pause playback.
10119c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     */
10129c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private void pauseAudioPlayback() {
10139c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // Shamelessly copied from MediaPlaybackService.java, which
10149c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // should be public, but isn't.
10159c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        Intent i = new Intent("com.android.music.musicservicecommand");
10169c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        i.putExtra("command", "pause");
10179c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
10189c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        sendBroadcast(i);
10199c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    }
10209c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
1021b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void startVideoRecording() {
1022b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "startVideoRecording");
1023b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (!mMediaRecorderRecording) {
1024b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10259a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            if (mStorageStatus != STORAGE_STATUS_OK) {
1026b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "Storage issue, ignore the start request");
1027b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
1028b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1029b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1030b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Check mMediaRecorder to see whether it is initialized or not.
1031b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            if (mMediaRecorder == null) {
1032b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                Log.e(TAG, "MediaRecorder is not initialized.");
1033b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
1034b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1035b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10369c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            pauseAudioPlayback();
10379c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
1038b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1039b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOnErrorListener(this);
10408d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                mMediaRecorder.setOnInfoListener(this);
1041b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.start();   // Recording is now started
1042b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (RuntimeException e) {
1043b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Could not start media recorder. ", e);
1044b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
1045b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1046b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorderRecording = true;
1047b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingStartTime = SystemClock.uptimeMillis();
1048b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateRecordingIndicator(true);
1049b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setText("");
1050b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setVisibility(View.VISIBLE);
1051b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mHandler.sendEmptyMessage(UPDATE_RECORD_TIME);
1052b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setScreenTimeoutInfinite();
1053b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1054b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1055b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1056b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateRecordingIndicator(boolean showRecording) {
1057d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        int drawableId = showRecording
1058059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin                ? R.drawable.ic_camera_indicator_stop
1059d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                : R.drawable.ic_camera_indicator_video;
1060b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Drawable drawable = getResources().getDrawable(drawableId);
1061b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setImageDrawable(drawable);
1062b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1063b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void stopVideoRecordingAndGetThumbnail() {
10659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        stopVideoRecording();
10669bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        acquireVideoThumb();
1067b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1068b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1069de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    private void stopVideoRecordingAndShowAlert() {
1070de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        stopVideoRecording();
10719bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        showAlert();
1072de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1073de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
10749bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void showAlert() {
1075059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.review_indicator).setVisibility(View.VISIBLE);
1076059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.video_indicator).setVisibility(View.INVISIBLE);
1077059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin
1078b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] pickIds = {R.id.attach, R.id.cancel};
1079b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] normalIds = {R.id.gallery, R.id.share, R.id.discard};
1080b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] alwaysOnIds = {R.id.play};
1081b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] hideIds = pickIds;
1082b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] connectIds = normalIds;
10839bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent) {
1084b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            hideIds = normalIds;
1085b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            connectIds = pickIds;
1086b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1087d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        for (int id : hideIds) {
1088b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostPictureAlert.findViewById(id).setVisibility(View.GONE);
1089b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1090b653f90f33c6f9e6b48dfab018dece9dd021a476Chih-Chung Chang
1091b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        connectAndFadeIn(connectIds);
1092b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        connectAndFadeIn(alwaysOnIds);
1093b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPostPictureAlert.setVisibility(View.VISIBLE);
1094059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        mVideoPreview.setVisibility(View.INVISIBLE);
10959bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
10969bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // There are two cases we are here:
10979bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // (1) We are in a capture video intent, and we are reviewing the video
1098095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin        //     we just taken.
10999bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // (2) The thumbnail button is clicked: we review the video associated
11009bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        //     with the thumbnail.
11019bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // For the second case, we copy the associated URI and filename to
11029bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // mCurrentVideoUri and mCurrentVideoFilename, so the video frame shown
11039bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // and the target for actions (play, delete, ...) will be correct.
11049bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
11059bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
1106cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync            if (mThumbController.isUriValid()) {
1107cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync                mCurrentVideoUri = mThumbController.getUri();
1108cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync                mCurrentVideoFilename = getDataPath(mCurrentVideoUri);
1109cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync            } else {
1110cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync                return;
1111cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync            }
11129bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
11139bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
11149bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        String path = mCurrentVideoFilename;
11159bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (path != null) {
1116101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            Bitmap videoFrame = Util.createVideoThumbnail(path);
11179bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mVideoFrame.setImageBitmap(videoFrame);
11189bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mVideoFrame.setVisibility(View.VISIBLE);
11199bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
1120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11229bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlert() {
1123059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        mVideoPreview.setVisibility(View.VISIBLE);
1124de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mVideoFrame.setVisibility(View.INVISIBLE);
1125de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mPostPictureAlert.setVisibility(View.INVISIBLE);
1126de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        showLastPictureButton();
1127de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1128de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
1129b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void connectAndFadeIn(int[] connectIds) {
1130d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        for (int id : connectIds) {
1131b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            View view = mPostPictureAlert.findViewById(id);
1132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            view.setOnClickListener(this);
1133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Animation animation = new AlphaAnimation(0F, 1F);
1134b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            animation.setDuration(500);
11359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            view.startAnimation(animation);
1136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1137b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11399bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private boolean isAlertVisible() {
1140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return mPostPictureAlert.getVisibility() == View.VISIBLE;
1141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void stopVideoRecording() {
1144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "stopVideoRecording");
1145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean needToRegisterRecording = false;
1146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mMediaRecorderRecording || mMediaRecorder != null) {
1147b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mMediaRecorderRecording && mMediaRecorder != null) {
1148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
1149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mMediaRecorder.setOnErrorListener(null);
11508d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    mMediaRecorder.setOnInfoListener(null);
1151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mMediaRecorder.stop();
1152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } catch (RuntimeException e) {
1153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.e(TAG, "stop fail: " + e.getMessage());
1154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
11558d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
1156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCurrentVideoFilename = mCameraVideoFilename;
1157d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Log.v(TAG, "Setting current video filename: "
1158d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        + mCurrentVideoFilename);
1159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                needToRegisterRecording = true;
1160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorderRecording = false;
1161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            releaseMediaRecorder();
1163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateRecordingIndicator(false);
1164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setVisibility(View.GONE);
1165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setScreenTimeoutLong();
1166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
11679a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (needToRegisterRecording && mStorageStatus == STORAGE_STATUS_OK) {
11689a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            registerVideo();
11699a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
1170b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFilename = null;
1172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFileDescriptor = null;
1173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutSystemDefault() {
1176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        clearScreenOnFlag();
1178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutLong() {
1181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenOnFlag();
1183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
1184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutInfinite() {
1187b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenOnFlag();
1189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void clearScreenOnFlag() {
1192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window w = getWindow();
1193d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1194d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if ((w.getAttributes().flags & flag) != 0) {
1195d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            w.clearFlags(flag);
1196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenOnFlag() {
1200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window w = getWindow();
1201d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1202d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if ((w.getAttributes().flags & flag) == 0) {
1203d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            w.addFlags(flag);
1204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1207b128446b7ef264c33e91e119391045156a19439bWu-cheng Li    private void hideAlertAndInitializeRecorder() {
12089bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlert();
1209b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        mRecorderInitialized = false;
1210b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        mHandler.sendEmptyMessage(INIT_RECORDER);
1211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12139bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void acquireVideoThumb() {
1214101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        Bitmap videoFrame = Util.createVideoThumbnail(mCurrentVideoFilename);
12159bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mThumbController.setData(mCurrentVideoUri, videoFrame);
1216de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1217de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12189bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void showLastPictureButton() {
12199bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
12209bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setVisibility(View.VISIBLE);
1221de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        }
12229bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    }
1223de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12249bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static ImageManager.DataLocation dataLocation() {
12259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        return ImageManager.DataLocation.EXTERNAL;
1226de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1227de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12289bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void updateLastVideo() {
122958e94eddd371a9bb7c04936dbeb99615fd1a0c2cChih-Chung Chang        IImageList list = ImageManager.allImages(
12309bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mContentResolver,
12319bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            dataLocation(),
12329bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.INCLUDE_VIDEOS,
12339bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.SORT_ASCENDING,
12349bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.CAMERA_IMAGE_BUCKET_ID);
12359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        int count = list.getCount();
12369bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (count > 0) {
1237d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            IImage image = list.getImageAt(count - 1);
12389bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            Uri uri = image.fullSizeImageUri();
12399bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(uri, image.miniThumbBitmap());
12409bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } else {
12419bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(null, null);
12429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
12439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        list.deactivate();
1244b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1245b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static final String[] DATA_PATH_PROJECTION = new String[] {
12479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        "_data"
12489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    };
12499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
12509bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private String getDataPath(Uri uri) {
12519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        Cursor c = null;
12529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        try {
1253d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            c = mContentResolver.query(uri, DATA_PATH_PROJECTION, null, null,
1254d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    null);
12559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (c != null && c.moveToFirst()) {
12569bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                return c.getString(0);
12579bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            } else {
12589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                return null;
12599bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            }
12609bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } finally {
126123c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            if (c != null) {
126223c51b794e95c201290e36737f379c4bb8eefeaeRay Chen                c.close();
126323c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            }
1264b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1265b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1266d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1267d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private void updateRecordingTime() {
126823c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        if (!mMediaRecorderRecording) {
126923c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            return;
127023c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        }
1271d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long now = SystemClock.uptimeMillis();
1272d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long delta = now - mRecordingStartTime;
1273d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1274d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // Starting a minute before reaching the max duration
1275d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // limit, we'll countdown the remaining time instead.
1276d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        boolean countdownRemainingTime =
127782ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang            (delta >= mMaxVideoDurationInMs - 60000);
1278d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1279d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (countdownRemainingTime) {
128082ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang            delta = Math.max(0, mMaxVideoDurationInMs - delta);
1281d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1282d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1283d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long seconds = (delta + 500) / 1000;  // round to nearest
1284d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long minutes = seconds / 60;
1285d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long hours = minutes / 60;
1286d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long remainderMinutes = minutes - (hours * 60);
1287d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long remainderSeconds = seconds - (minutes * 60);
1288d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1289d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String secondsString = Long.toString(remainderSeconds);
1290d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (secondsString.length() < 2) {
1291d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            secondsString = "0" + secondsString;
1292d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1293d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String minutesString = Long.toString(remainderMinutes);
1294d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (minutesString.length() < 2) {
1295d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            minutesString = "0" + minutesString;
1296d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1297d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String text = minutesString + ":" + secondsString;
1298d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (hours > 0) {
1299d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            String hoursString = Long.toString(hours);
1300d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            if (hoursString.length() < 2) {
1301d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                hoursString = "0" + hoursString;
1302d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            }
1303d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            text = hoursString + ":" + text;
1304d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1305d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mRecordingTimeView.setText(text);
1306d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1307d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (mRecordingTimeCountsDown != countdownRemainingTime) {
1308d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // Avoid setting the color on every update, do it only
1309d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // when it needs changing.
1310d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1311d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mRecordingTimeCountsDown = countdownRemainingTime;
1312d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1313d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int color = getResources().getColor(
1314d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    countdownRemainingTime
1315d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    ? R.color.recording_time_remaining_text
1316d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    : R.color.recording_time_elapsed_text);
1317d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1318d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mRecordingTimeView.setTextColor(color);
1319d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1320d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1321d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // Work around a limitation of the T-Mobile G1: The T-Mobile
1322d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // hardware blitter can't pixel-accurately scale and clip at the
1323d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // same time, and the SurfaceFlinger doesn't attempt to work around
1324d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // this limitation. In order to avoid visual corruption we must
1325d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // manually refresh the entire surface view when changing any
1326d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // overlapping view's contents.
1327d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mVideoPreview.invalidate();
1328d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mHandler.sendEmptyMessageDelayed(UPDATE_RECORD_TIME, 1000);
1329d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    }
1330b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project}
1331