VideoCamera.java revision b128446b7ef264c33e91e119391045156a19439b
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() {
218ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li                mCameraDevice = android.hardware.Camera.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
295b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.gallery:
2960a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang                gotoGallery();
297b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
298b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.attach:
300b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doReturnToCaller(true);
301b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
302b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
303b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.cancel:
304b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doReturnToCaller(false);
305b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
306b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
307b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.discard: {
3087638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                Runnable deleteCallback = new Runnable() {
3097638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                    public void run() {
310b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                        discardCurrentVideoAndInitRecorder();
3117638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                    }
3127638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                };
3137638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                MenuHelper.deleteVideo(this, deleteCallback);
314b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
315b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
316b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
317b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.share: {
318e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                startShareVideoActivity();
319b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
320b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
321b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
322b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.play: {
323b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doPlayCurrentVideo();
324b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
325b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
326de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
327059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            case R.id.review_button: {
3289bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndShowAlert();
329de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                break;
330de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            }
331b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
333b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
334b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onShutterButtonFocus(ShutterButton button, boolean pressed) {
335de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        // Do nothing (everything happens in onShutterButtonClick).
336de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
337de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
338de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    public void onShutterButtonClick(ShutterButton button) {
339b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (button.getId()) {
340059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin            case R.id.video_button:
341de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                if (mMediaRecorderRecording) {
3429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    if (mIsVideoCaptureIntent) {
343de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                        stopVideoRecordingAndShowAlert();
344b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } else {
3459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        stopVideoRecordingAndGetThumbnail();
346b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                        mRecorderInitialized = false;
347b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                        initializeRecorder();
3489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    }
3499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                } else if (isAlertVisible()) {
3509bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    if (mIsVideoCaptureIntent) {
351b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                        discardCurrentVideoAndInitRecorder();
3529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    } else {
353b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                        hideAlertAndInitializeRecorder();
354b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
355b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                } else if (mRecorderInitialized) {
356b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                    // If the click comes before recorder initialization, it is
357b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                    // ignored. If users click the button during initialization,
358b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                    // the event is put in the queue and record will be started
359b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                    // eventually.
360de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    startVideoRecording();
361b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
362b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
363b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
364b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
365b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
366b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doPlayCurrentVideo() {
3670a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang        Log.v(TAG, "Playing current video: " + mCurrentVideoUri);
368b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri);
369b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
370b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            startActivity(intent);
371b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (android.content.ActivityNotFoundException ex) {
372b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex);
373b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
374b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
375b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
376b128446b7ef264c33e91e119391045156a19439bWu-cheng Li    private void discardCurrentVideoAndInitRecorder() {
377b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        deleteCurrentVideo();
378b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        hideAlertAndInitializeRecorder();
379b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
380b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
381b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private OnScreenHint mStorageHint;
382b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3839a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private void updateAndShowStorageHint(boolean mayHaveSd) {
3849a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mStorageStatus = getStorageStatus(mayHaveSd);
3859a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        showStorageHint();
3869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    }
3879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
3889a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private void showStorageHint() {
389b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String errorMessage = null;
3909a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        switch (mStorageStatus) {
3919a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        case STORAGE_STATUS_NONE:
392b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            errorMessage = getString(R.string.no_storage);
3939a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            break;
3949a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        case STORAGE_STATUS_LOW:
395b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            errorMessage = getString(R.string.spaceIsLow_content);
396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
397b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (errorMessage != null) {
398b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStorageHint == null) {
399b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint = OnScreenHint.makeText(this, errorMessage);
400b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
401b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint.setText(errorMessage);
402b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
403b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.show();
404b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else if (mStorageHint != null) {
405b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
406b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
407b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
408b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
409b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4109a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private int getStorageStatus(boolean mayHaveSd) {
4119a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        long remaining = mayHaveSd ? getAvailableStorage() : NO_STORAGE_ERROR;
4129a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (remaining == NO_STORAGE_ERROR) {
4139a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            return STORAGE_STATUS_NONE;
4149a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
4159a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        return remaining < LOW_STORAGE_THRESHOLD
4169a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                ? STORAGE_STATUS_LOW : STORAGE_STATUS_OK;
4179a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    }
4189a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
419845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private void readVideoSizePreference() {
420845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        boolean videoQualityHigh = getBooleanPreference(
421845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang                CameraSettings.KEY_VIDEO_QUALITY,
422845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang                CameraSettings.DEFAULT_VIDEO_QUALITY_VALUE);
423845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
42482ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang        // 1 minute = 60000ms
42582ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang        mMaxVideoDurationInMs = 60000 * getIntPreference(
42682ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang                CameraSettings.KEY_VIDEO_DURATION,
42782ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang                CameraSettings.DEFAULT_VIDEO_DURATION_VALUE);
42882ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang
429845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        Intent intent = getIntent();
430845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) {
431845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            int extraVideoQuality = intent.getIntExtra(
432845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang                    MediaStore.EXTRA_VIDEO_QUALITY, 0);
433845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            videoQualityHigh = (extraVideoQuality > 0);
434845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
435845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
436845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        if (videoQualityHigh) {
437845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            // CIF size
438845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoWidth = 352;
439845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoHeight = 288;
440845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        } else {
441845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            // QCIF size
442845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoWidth = 176;
443845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mVideoHeight = 144;
444845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
445845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
446845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
447b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
448b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onResume() {
449b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onResume();
450845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mPausing = false;
451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
452b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutLong();
453845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        readVideoSizePreference();
454b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
455b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // install an intent filter to receive SD card related events.
456d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        IntentFilter intentFilter =
457d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
458b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_EJECT);
459b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
460b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
461b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
462b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addDataScheme("file");
463b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        registerReceiver(mReceiver, intentFilter);
4649a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mStorageStatus = getStorageStatus(true);
4659a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
4669a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mHandler.postDelayed(new Runnable() {
4679a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            public void run() {
4689a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                showStorageHint();
4699a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            }
4709a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }, 200);
471b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
472b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        if (mSurfaceHolder != null) {
473b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            startPreview();
474b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            mRecorderInitialized = false;
475b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            mHandler.sendEmptyMessage(INIT_RECORDER);
476b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        }
477b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
478b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
479845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private void setCameraParameters() {
480845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        android.hardware.Camera.Parameters param;
481845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        param = mCameraDevice.getParameters();
482845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        param.setPreviewSize(mVideoWidth, mVideoHeight);
483845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice.setParameters(param);
484845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
485845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
486845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    // Precondition: mSurfaceHolder != null
487acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang    // Returns true if starting preview succeeds.
488acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang    private boolean startPreview() {
489059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.review_indicator).setVisibility(View.INVISIBLE);
490059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.video_indicator).setVisibility(View.VISIBLE);
491059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin
492845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        Log.v(TAG, "startPreview");
493ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        if (mPreviewing) {
494d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            // We should just return here, but we stop and start again to avoid
495d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            // the bug in driver.
496d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            mCameraDevice.lock();
497d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            mCameraDevice.stopPreview();
498d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            mCameraDevice.startPreview();
499d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang            mCameraDevice.unlock();
500acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang            return true;
501845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
502ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
503ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        if (mCameraDevice == null) {
504ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // If the activity is paused and resumed, camera device has been
505ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            // released and we need to open the camera.
506ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            mCameraDevice = android.hardware.Camera.open();
507ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        }
508ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
509845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        setCameraParameters();
510845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        try {
511845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.setPreviewDisplay(mSurfaceHolder);
512845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        } catch (IOException ex) {
513845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.release();
514845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice = null;
515845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            Log.e(TAG, "failed to set preview display");
516acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang            return false;
517845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
518ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li
519845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        try {
520845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.startPreview();
521ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li            mPreviewing = true;
522845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        } catch (Throwable ex) {
523845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            // TODO: change Throwable to IOException once
524845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            //      android.hardware.Camera.startPreview properly declares
525845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            //      that it throws IOException.
526845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice.release();
527845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            mCameraDevice = null;
528845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            Log.e(TAG, "failed to start preview");
529acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang            return false;
530845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
531845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice.unlock();
532acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang        return true;
533845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
534845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
535d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang    private void closeCamera() {
536d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang        Log.v(TAG, "closeCamera");
537845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        if (mCameraDevice == null) {
538845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            Log.d(TAG, "already stopped.");
539845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang            return;
540845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        }
541fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        // If we don't lock the camera, release() will fail.
542fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        mCameraDevice.lock();
543845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice.release();
544845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mCameraDevice = null;
545ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        mPreviewing = false;
546845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    }
547845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
548b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
549b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onStop() {
550b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutSystemDefault();
551b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onStop();
552b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
553b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
554b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
555b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    protected void onPause() {
556b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPause();
557b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
558fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        mPausing = true;
559fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li
5609bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // This is similar to what mShutterButton.performClick() does,
5619bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // but not quite the same.
5629bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mMediaRecorderRecording) {
5639bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (mIsVideoCaptureIntent) {
5649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndShowAlert();
5659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            } else {
5669bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndGetThumbnail();
5679bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            }
5689bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } else {
5699bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            stopVideoRecording();
5709bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
571fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        closeCamera();
572b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5739c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        unregisterReceiver(mReceiver);
574b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutSystemDefault();
575b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5769bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
5779bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.storeData(ImageManager.getLastVideoThumbPath());
5789bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
579095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin
580b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mStorageHint != null) {
581b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
582b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
583b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
584845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang
585b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        mHandler.removeMessages(INIT_RECORDER);
586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
588b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
590fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        // Do not handle any key if the activity is paused.
591fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        if (mPausing) {
592fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li            return true;
593fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li        }
594fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li
595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutLong();
596b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
597b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (keyCode) {
598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_BACK:
599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mMediaRecorderRecording) {
600de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
602d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                } else if (isAlertVisible()) {
603b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                    hideAlertAndInitializeRecorder();
604b64d345c9d51cabce43b5191532a0c185d2a70a5The 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_CAMERA:
608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
609de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
610b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
611b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
612de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                break;
613b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_CENTER:
614b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
615de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
616de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    return true;
617b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
618b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
619b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_MENU:
620b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mMediaRecorderRecording) {
621de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
622b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
623b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
624b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
625b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
626b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyDown(keyCode, event);
628b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
629b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
630b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
631b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
632b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch(keyCode) {
633b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case KeyEvent.KEYCODE_CAMERA:
634b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mShutterButton.setPressed(false);
635b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return true;
636b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
637b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyUp(keyCode, event);
638b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
639b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
640b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
641314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber        if (mPausing) {
642314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // We're pausing, the screen is off and we already stopped
643314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // video recording. We don't want to start the camera again
644314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // in this case in order to conserve power.
645314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // The fact that surfaceChanged is called _after_ an onPause appears
646314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // to be legitimate since in that case the lockscreen always returns
647314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // to portrait orientation possibly triggering the notification.
648314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            return;
649314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber        }
650314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber
651b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        if (mMediaRecorderRecording) {
652b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            stopVideoRecording();
653b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        }
654b128446b7ef264c33e91e119391045156a19439bWu-cheng Li
655b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        // Start the preview if it is not started yet. Preview may be already
656b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        // started in onResume and then surfaceChanged is called due to
657b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        // orientation change.
658b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        if (!mPreviewing) {
659b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            startPreview();
660b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            mRecorderInitialized = false;
661b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            mHandler.sendEmptyMessage(INIT_RECORDER);
662b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        }
663b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
665b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceCreated(SurfaceHolder holder) {
666b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = holder;
667b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
668b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceDestroyed(SurfaceHolder holder) {
670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = null;
671b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
672b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6730a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang    private void gotoGallery() {
674b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.gotoCameraVideoGallery(this);
675b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
676b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
677b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
678b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onPrepareOptionsMenu(Menu menu) {
679b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPrepareOptionsMenu(menu);
680b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
681b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int i = 1; i <= MenuHelper.MENU_ITEM_MAX; i++) {
682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (i != MenuHelper.GENERIC_ITEM) {
683b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                menu.setGroupVisible(i, false);
684b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
685b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
686b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
687b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        menu.setGroupVisible(MenuHelper.VIDEO_MODE_ITEM, true);
688b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
689b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
690b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
691b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
692b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onCreateOptionsMenu(Menu menu) {
693b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreateOptionsMenu(menu);
694b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6959bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent) {
696b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // No options menu for attach mode.
697b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
698b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
699b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            addBaseMenuItems(menu);
700d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int menuFlags = MenuHelper.INCLUDE_ALL
701d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    & ~MenuHelper.INCLUDE_ROTATE_MENU
702095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin                    & ~MenuHelper.INCLUDE_DETAILS_MENU;
703b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            MenuHelper.addImageMenuItems(
704b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    menu,
705095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin                    menuFlags,
706b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    false,
707b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    VideoCamera.this,
70823c51b794e95c201290e36737f379c4bb8eefeaeRay Chen                    mHandler,
709b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // Handler for deletion
710b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    new Runnable() {
711b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run() {
712b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            // What do we do here?
713b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            // mContentResolver.delete(uri, null, null);
714b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
715b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    },
716b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    new MenuHelper.MenuInvoker() {
717b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run(final MenuHelper.MenuCallback cb) {
718b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
719b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    });
720b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
721d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.IMAGE_SAVING_ITEM,
722d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_SAVE_GALLERY_PHOTO, 0,
723d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    R.string.camera_gallery_photos_text)
724d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(
725d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    new MenuItem.OnMenuItemClickListener() {
726d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
727d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
728d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
729d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
730d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
731b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
732b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
733b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
734b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
735b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
736b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean isVideoCaptureIntent() {
737b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String action = getIntent().getAction();
738b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action));
739b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
740b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
741b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doReturnToCaller(boolean success) {
742b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent resultIntent = new Intent();
743b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int resultCode;
744b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (success) {
745b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultCode = RESULT_OK;
746b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultIntent.setData(mCurrentVideoUri);
747b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
748b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultCode = RESULT_CANCELED;
749b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
750b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setResult(resultCode, resultIntent);
751b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        finish();
752b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
753b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
754b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
755b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * Returns
756b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * @return number of bytes available, or an ERROR code.
757b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
758b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static long getAvailableStorage() {
759b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
760b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (!ImageManager.hasStorage()) {
761b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return NO_STORAGE_ERROR;
762b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
763d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                String storageDirectory = Environment
764d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        .getExternalStorageDirectory().toString();
765b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                StatFs stat = new StatFs(storageDirectory);
766d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                return ((long) stat.getAvailableBlocks()
767d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        * (long) stat.getBlockSize());
768b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
76923c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        } catch (RuntimeException ex) {
770b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // if we can't stat the filesystem then we don't know how many
771b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // free bytes exist.  It might be zero but just leave it
772b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // blank since we really don't know.
773b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return CANNOT_STAT_ERROR;
774b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
775b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
776b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
777b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void cleanupEmptyFile() {
778b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraVideoFilename != null) {
779b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            File f = new File(mCameraVideoFilename);
780b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (f.length() == 0 && f.delete()) {
781b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project              Log.v(TAG, "Empty video file deleted: " + mCameraVideoFilename);
782b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project              mCameraVideoFilename = null;
783b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
784b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
785b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
786b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
787845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang    private android.hardware.Camera mCameraDevice;
788b128446b7ef264c33e91e119391045156a19439bWu-cheng Li    // initializeRecorder() prepares media recorder. Return false if fails.
789b128446b7ef264c33e91e119391045156a19439bWu-cheng Li    private boolean initializeRecorder() {
790b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        Log.v(TAG, "initializeRecorder");
791b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        if (mRecorderInitialized) return true;
7929bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
793b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        // We will call initializeRecorder() again when the alert is hidden.
79423c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        if (isAlertVisible()) {
79523c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            return false;
79623c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        }
7979bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
798b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent intent = getIntent();
799b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bundle myExtras = intent.getExtras();
800b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
8019bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent && myExtras != null) {
802b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
803b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (saveUri != null) {
804b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
805b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCameraVideoFileDescriptor = mContentResolver.
806b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        openFileDescriptor(saveUri, "rw").getFileDescriptor();
807b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCurrentVideoUri = saveUri;
808d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                } catch (java.io.FileNotFoundException ex) {
809b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // invalid uri
810b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.e(TAG, ex.toString());
811b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
812b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
813b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
814b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        releaseMediaRecorder();
815b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
816b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder = new MediaRecorder();
817b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
818845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mMediaRecorder.setCamera(mCameraDevice);
819d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
820b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
821b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
82282ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang        mMediaRecorder.setMaxDuration(mMaxVideoDurationInMs);
8238d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
8249a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (mStorageStatus != STORAGE_STATUS_OK) {
825b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.setOutputFile("/dev/null");
826b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
827d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // We try Uri in intent first. If it doesn't work, use our own
828d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // instead.
829b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCameraVideoFileDescriptor != null) {
830b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOutputFile(mCameraVideoFileDescriptor);
831b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
832b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                createVideoPath();
833b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOutputFile(mCameraVideoFilename);
834b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
835b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
836b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
837b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // Use the same frame rate for both, since internally
838b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // if the frame rate is too large, it can cause camera to become
839b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // unstable. We need to fix the MediaRecorder to disable the support
840b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // of setting frame rate for now.
841b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoFrameRate(20);
842845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang        mMediaRecorder.setVideoSize(mVideoWidth, mVideoHeight);
843b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
844d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
845b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
846de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
847de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        long remaining = getAvailableStorage();
848de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        // remaining >= LOW_STORAGE_THRESHOLD at this point, reserve a quarter
849d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // of that to make it more likely that recording can complete
850d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // successfully.
851de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        try {
852d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mMediaRecorder.setMaxFileSize(remaining -
853d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    LOW_STORAGE_THRESHOLD / 4);
854de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        } catch (RuntimeException exception) {
855de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // We are going to ignore failure of setMaxFileSize here, as
856de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // a) The composer selected may simply not support it, or
857de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // b) The underlying media framework may not handle 64-bit range
858de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            //    on the size restriction.
859de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        }
860de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
861b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
862b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.prepare();
863b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (IOException exception) {
864b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "prepare failed for " + mCameraVideoFilename);
865b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            releaseMediaRecorder();
866b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // TODO: add more exception handling logic here
867b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
868b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
869b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorderRecording = false;
8709bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
871ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li        // Update the last video thumbnail.
872b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        if (!mIsVideoCaptureIntent) {
873b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            if (!mThumbController.isUriValid()) {
874b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                updateLastVideo();
875b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            }
876b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            mThumbController.updateDisplayIfNeeded();
8779bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
878b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        mRecorderInitialized = true;
879b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
880b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
881b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
882b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void releaseMediaRecorder() {
883b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Releasing media recorder.");
884b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mMediaRecorder != null) {
885b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cleanupEmptyFile();
886b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.reset();
887b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.release();
888b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder = null;
889b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
890b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
891b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
892b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int getIntPreference(String key, int defaultValue) {
893b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String s = mPreferences.getString(key, "");
894b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int result = defaultValue;
895b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
896b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            result = Integer.parseInt(s);
897b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (NumberFormatException e) {
898b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Ignore, result is already the default value.
899b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
900b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return result;
901b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
902b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
903b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean getBooleanPreference(String key, boolean defaultValue) {
904b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return getIntPreference(key, defaultValue ? 1 : 0) != 0;
905b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
906b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
907b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void createVideoPath() {
908b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        long dateTaken = System.currentTimeMillis();
909b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String title = createName(dateTaken);
910b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String displayName = title + ".3gp"; // Used when emailing.
911b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME;
912b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        File cameraDir = new File(cameraDirPath);
913b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        cameraDir.mkdirs();
914b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SimpleDateFormat dateFormat = new SimpleDateFormat(
915b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                getString(R.string.video_file_name_format));
916b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Date date = new Date(dateTaken);
917b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String filepart = dateFormat.format(date);
918b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String filename = cameraDirPath + "/" + filepart + ".3gp";
919b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ContentValues values = new ContentValues(7);
920b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.TITLE, title);
921b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DISPLAY_NAME, displayName);
922b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DATE_TAKEN, dateTaken);
923b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.MIME_TYPE, "video/3gpp");
924b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DATA, filename);
925b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFilename = filename;
926b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Current camera video filename: " + mCameraVideoFilename);
927b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCurrentVideoValues = values;
928b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
929b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
930b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void registerVideo() {
931b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraVideoFileDescriptor == null) {
932b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri videoTable = Uri.parse("content://media/external/video/media");
933b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoUri = mContentResolver.insert(videoTable,
934b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCurrentVideoValues);
935b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "Current video URI: " + mCurrentVideoUri);
936b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
937b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCurrentVideoValues = null;
938b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
939b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
940b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void deleteCurrentVideo() {
941b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCurrentVideoFilename != null) {
942b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            deleteVideoFile(mCurrentVideoFilename);
943b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoFilename = null;
944b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
945b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCurrentVideoUri != null) {
946b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mContentResolver.delete(mCurrentVideoUri, null, null);
947b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoUri = null;
948b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
949de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        updateAndShowStorageHint(true);
950b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
951b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
952b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void deleteVideoFile(String fileName) {
953b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Deleting video " + fileName);
954b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        File f = new File(fileName);
955d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (!f.delete()) {
956b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "Could not delete " + fileName);
957b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
958b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
959b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
960b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void addBaseMenuItems(Menu menu) {
961b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.addSwitchModeMenuItem(menu, this, false);
962b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
963d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.IMAGE_MODE_ITEM,
964d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_GALLERY_PHOTOS, 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 gallery = menu.add(MenuHelper.VIDEO_MODE_ITEM,
976d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_GALLERY_VIDEOS, 0, R.string.camera_gallery_photos_text)
977d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
978d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
979d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
980d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
981d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
982d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
983b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
984b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
985b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
986b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
987d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        MenuItem item = menu.add(MenuHelper.GENERIC_ITEM, MENU_SETTINGS, 0,
988d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                R.string.settings)
989d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                .setOnMenuItemClickListener(new OnMenuItemClickListener() {
990d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    public boolean onMenuItemClick(MenuItem item) {
991d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        Intent intent = new Intent();
992d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        intent.setClass(VideoCamera.this, CameraSettings.class);
993d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        startActivity(intent);
994d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        return true;
995d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    }
996d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                });
997b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        item.setIcon(android.R.drawable.ic_menu_preferences);
998b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
999b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1000b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // from MediaRecorder.OnErrorListener
1001b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onError(MediaRecorder mr, int what, int extra) {
1002b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) {
1003b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // We may have run out of space on the sdcard.
1004b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            stopVideoRecording();
10059a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            updateAndShowStorageHint(true);
1006b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1007b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1008b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10098d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    // from MediaRecorder.OnInfoListener
10108d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    public void onInfo(MediaRecorder mr, int what, int extra) {
10118d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
1012de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            mShutterButton.performClick();
1013d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        } else if (what
1014d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
1015de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            mShutterButton.performClick();
1016de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            updateAndShowStorageHint(true);
10178d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        }
10188d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    }
10198d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
10209c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    /*
10219c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     * Make sure we're not recording music playing in the background, ask
10229c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     * the MediaPlaybackService to pause playback.
10239c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     */
10249c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private void pauseAudioPlayback() {
10259c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // Shamelessly copied from MediaPlaybackService.java, which
10269c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // should be public, but isn't.
10279c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        Intent i = new Intent("com.android.music.musicservicecommand");
10289c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        i.putExtra("command", "pause");
10299c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
10309c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        sendBroadcast(i);
10319c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    }
10329c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
1033b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void startVideoRecording() {
1034b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "startVideoRecording");
1035b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (!mMediaRecorderRecording) {
1036b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10379a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            if (mStorageStatus != STORAGE_STATUS_OK) {
1038b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "Storage issue, ignore the start request");
1039b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
1040b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1041b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1042b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Check mMediaRecorder to see whether it is initialized or not.
1043b128446b7ef264c33e91e119391045156a19439bWu-cheng Li            if (mMediaRecorder == null) {
1044b128446b7ef264c33e91e119391045156a19439bWu-cheng Li                Log.e(TAG, "MediaRecorder is not initialized.");
1045b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
1046b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1047b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10489c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            pauseAudioPlayback();
10499c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
1050b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
1051b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOnErrorListener(this);
10528d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                mMediaRecorder.setOnInfoListener(this);
1053b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.start();   // Recording is now started
1054b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (RuntimeException e) {
1055b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Could not start media recorder. ", e);
1056b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
1057b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1058b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorderRecording = true;
1059b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingStartTime = SystemClock.uptimeMillis();
1060b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateRecordingIndicator(true);
1061b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setText("");
1062b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setVisibility(View.VISIBLE);
1063b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mHandler.sendEmptyMessage(UPDATE_RECORD_TIME);
1064b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setScreenTimeoutInfinite();
1065b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1066b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1067b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1068b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateRecordingIndicator(boolean showRecording) {
1069d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        int drawableId = showRecording
1070059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin                ? R.drawable.ic_camera_indicator_stop
1071d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                : R.drawable.ic_camera_indicator_video;
1072b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Drawable drawable = getResources().getDrawable(drawableId);
1073b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setImageDrawable(drawable);
1074b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1075b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10769bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void stopVideoRecordingAndGetThumbnail() {
10779bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        stopVideoRecording();
10789bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        acquireVideoThumb();
1079b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1080b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1081de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    private void stopVideoRecordingAndShowAlert() {
1082de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        stopVideoRecording();
10839bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        showAlert();
1084de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1085de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
10869bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void showAlert() {
1087059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.review_indicator).setVisibility(View.VISIBLE);
1088059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        findViewById(R.id.video_indicator).setVisibility(View.INVISIBLE);
1089059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin
1090b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] pickIds = {R.id.attach, R.id.cancel};
1091b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] normalIds = {R.id.gallery, R.id.share, R.id.discard};
1092b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] alwaysOnIds = {R.id.play};
1093b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] hideIds = pickIds;
1094b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] connectIds = normalIds;
10959bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent) {
1096b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            hideIds = normalIds;
1097b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            connectIds = pickIds;
1098b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1099d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        for (int id : hideIds) {
1100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostPictureAlert.findViewById(id).setVisibility(View.GONE);
1101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1102b653f90f33c6f9e6b48dfab018dece9dd021a476Chih-Chung Chang
1103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        connectAndFadeIn(connectIds);
1104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        connectAndFadeIn(alwaysOnIds);
1105b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPostPictureAlert.setVisibility(View.VISIBLE);
1106059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        mVideoPreview.setVisibility(View.INVISIBLE);
11079bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
11089bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // There are two cases we are here:
11099bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // (1) We are in a capture video intent, and we are reviewing the video
1110095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin        //     we just taken.
11119bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // (2) The thumbnail button is clicked: we review the video associated
11129bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        //     with the thumbnail.
11139bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // For the second case, we copy the associated URI and filename to
11149bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // mCurrentVideoUri and mCurrentVideoFilename, so the video frame shown
11159bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // and the target for actions (play, delete, ...) will be correct.
11169bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
11179bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
1118cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync            if (mThumbController.isUriValid()) {
1119cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync                mCurrentVideoUri = mThumbController.getUri();
1120cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync                mCurrentVideoFilename = getDataPath(mCurrentVideoUri);
1121cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync            } else {
1122cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync                return;
1123cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync            }
11249bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
11259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
11269bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        String path = mCurrentVideoFilename;
11279bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (path != null) {
1128101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            Bitmap videoFrame = Util.createVideoThumbnail(path);
11299bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mVideoFrame.setImageBitmap(videoFrame);
11309bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mVideoFrame.setVisibility(View.VISIBLE);
11319bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
1132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11349bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlert() {
1135059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin        mVideoPreview.setVisibility(View.VISIBLE);
1136de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mVideoFrame.setVisibility(View.INVISIBLE);
1137de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mPostPictureAlert.setVisibility(View.INVISIBLE);
1138de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        showLastPictureButton();
1139de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1140de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
1141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void connectAndFadeIn(int[] connectIds) {
1142d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        for (int id : connectIds) {
1143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            View view = mPostPictureAlert.findViewById(id);
1144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            view.setOnClickListener(this);
1145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Animation animation = new AlphaAnimation(0F, 1F);
1146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            animation.setDuration(500);
11479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            view.startAnimation(animation);
1148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1150b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private boolean isAlertVisible() {
1152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return mPostPictureAlert.getVisibility() == View.VISIBLE;
1153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void stopVideoRecording() {
1156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "stopVideoRecording");
1157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean needToRegisterRecording = false;
1158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mMediaRecorderRecording || mMediaRecorder != null) {
1159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mMediaRecorderRecording && mMediaRecorder != null) {
1160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
1161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mMediaRecorder.setOnErrorListener(null);
11628d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    mMediaRecorder.setOnInfoListener(null);
1163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mMediaRecorder.stop();
1164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } catch (RuntimeException e) {
1165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.e(TAG, "stop fail: " + e.getMessage());
1166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
11678d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
1168b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCurrentVideoFilename = mCameraVideoFilename;
1169d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Log.v(TAG, "Setting current video filename: "
1170d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        + mCurrentVideoFilename);
1171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                needToRegisterRecording = true;
1172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorderRecording = false;
1173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            releaseMediaRecorder();
1175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateRecordingIndicator(false);
1176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setVisibility(View.GONE);
1177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setScreenTimeoutLong();
1178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
11799a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (needToRegisterRecording && mStorageStatus == STORAGE_STATUS_OK) {
11809a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            registerVideo();
11819a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
1182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFilename = null;
1184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFileDescriptor = null;
1185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1187b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutSystemDefault() {
1188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        clearScreenOnFlag();
1190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutLong() {
1193b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1194b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenOnFlag();
1195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
1196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutInfinite() {
1199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenOnFlag();
1201b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1203b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void clearScreenOnFlag() {
1204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window w = getWindow();
1205d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1206d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if ((w.getAttributes().flags & flag) != 0) {
1207d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            w.clearFlags(flag);
1208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1210b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenOnFlag() {
1212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window w = getWindow();
1213d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1214d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if ((w.getAttributes().flags & flag) == 0) {
1215d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            w.addFlags(flag);
1216b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1217b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1218b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1219b128446b7ef264c33e91e119391045156a19439bWu-cheng Li    private void hideAlertAndInitializeRecorder() {
12209bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlert();
1221b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        mRecorderInitialized = false;
1222b128446b7ef264c33e91e119391045156a19439bWu-cheng Li        mHandler.sendEmptyMessage(INIT_RECORDER);
1223b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void acquireVideoThumb() {
1226101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        Bitmap videoFrame = Util.createVideoThumbnail(mCurrentVideoFilename);
12279bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mThumbController.setData(mCurrentVideoUri, videoFrame);
1228de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1229de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12309bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void showLastPictureButton() {
12319bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
12329bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setVisibility(View.VISIBLE);
1233de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        }
12349bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    }
1235de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12369bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static ImageManager.DataLocation dataLocation() {
12379bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        return ImageManager.DataLocation.EXTERNAL;
1238de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1239de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
12409bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void updateLastVideo() {
124158e94eddd371a9bb7c04936dbeb99615fd1a0c2cChih-Chung Chang        IImageList list = ImageManager.allImages(
12429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mContentResolver,
12439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            dataLocation(),
12449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.INCLUDE_VIDEOS,
12459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.SORT_ASCENDING,
12469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.CAMERA_IMAGE_BUCKET_ID);
12479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        int count = list.getCount();
12489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (count > 0) {
1249d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            IImage image = list.getImageAt(count - 1);
12509bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            Uri uri = image.fullSizeImageUri();
12519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(uri, image.miniThumbBitmap());
12529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } else {
12539bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(null, null);
12549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
12559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        list.deactivate();
1256b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1257b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
12589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static final String[] DATA_PATH_PROJECTION = new String[] {
12599bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        "_data"
12609bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    };
12619bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
12629bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private String getDataPath(Uri uri) {
12639bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        Cursor c = null;
12649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        try {
1265d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            c = mContentResolver.query(uri, DATA_PATH_PROJECTION, null, null,
1266d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    null);
12679bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (c != null && c.moveToFirst()) {
12689bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                return c.getString(0);
12699bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            } else {
12709bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                return null;
12719bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            }
12729bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } finally {
127323c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            if (c != null) {
127423c51b794e95c201290e36737f379c4bb8eefeaeRay Chen                c.close();
127523c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            }
1276b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1277b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1278d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1279d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private void updateRecordingTime() {
128023c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        if (!mMediaRecorderRecording) {
128123c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            return;
128223c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        }
1283d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long now = SystemClock.uptimeMillis();
1284d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long delta = now - mRecordingStartTime;
1285d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1286d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // Starting a minute before reaching the max duration
1287d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // limit, we'll countdown the remaining time instead.
1288d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        boolean countdownRemainingTime =
128982ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang            (delta >= mMaxVideoDurationInMs - 60000);
1290d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1291d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (countdownRemainingTime) {
129282ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang            delta = Math.max(0, mMaxVideoDurationInMs - delta);
1293d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1294d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1295d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long seconds = (delta + 500) / 1000;  // round to nearest
1296d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long minutes = seconds / 60;
1297d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long hours = minutes / 60;
1298d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long remainderMinutes = minutes - (hours * 60);
1299d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long remainderSeconds = seconds - (minutes * 60);
1300d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1301d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String secondsString = Long.toString(remainderSeconds);
1302d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (secondsString.length() < 2) {
1303d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            secondsString = "0" + secondsString;
1304d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1305d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String minutesString = Long.toString(remainderMinutes);
1306d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (minutesString.length() < 2) {
1307d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            minutesString = "0" + minutesString;
1308d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1309d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String text = minutesString + ":" + secondsString;
1310d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (hours > 0) {
1311d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            String hoursString = Long.toString(hours);
1312d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            if (hoursString.length() < 2) {
1313d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                hoursString = "0" + hoursString;
1314d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            }
1315d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            text = hoursString + ":" + text;
1316d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1317d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mRecordingTimeView.setText(text);
1318d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1319d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (mRecordingTimeCountsDown != countdownRemainingTime) {
1320d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // Avoid setting the color on every update, do it only
1321d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // when it needs changing.
1322d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1323d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mRecordingTimeCountsDown = countdownRemainingTime;
1324d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1325d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int color = getResources().getColor(
1326d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    countdownRemainingTime
1327d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    ? R.color.recording_time_remaining_text
1328d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    : R.color.recording_time_elapsed_text);
1329d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1330d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mRecordingTimeView.setTextColor(color);
1331d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1332d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1333d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // Work around a limitation of the T-Mobile G1: The T-Mobile
1334d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // hardware blitter can't pixel-accurately scale and clip at the
1335d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // same time, and the SurfaceFlinger doesn't attempt to work around
1336d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // this limitation. In order to avoid visual corruption we must
1337d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // manually refresh the entire surface view when changing any
1338d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // overlapping view's contents.
1339d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mVideoPreview.invalidate();
1340d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mHandler.sendEmptyMessageDelayed(UPDATE_RECORD_TIME, 1000);
1341d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    }
1342b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project}
1343