VideoCamera.java revision d8209aa01ae56ea27f551f621b419251bf80b265
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 Linimport com.android.camera.gallery.Util;
22101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
23b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.app.Activity;
24b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.BroadcastReceiver;
25b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.ContentResolver;
26b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.ContentValues;
27b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Context;
28b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Intent;
29b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.IntentFilter;
30b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.SharedPreferences;
31095afa19556bf550262e3cccb9edacc04e6f726aOwen Linimport android.database.Cursor;
32b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.Bitmap;
33b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.drawable.Drawable;
34b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.location.LocationManager;
35b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.media.MediaRecorder;
36b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.net.Uri;
37b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Bundle;
38b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Environment;
39b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Handler;
40b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Message;
41b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.StatFs;
42b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.SystemClock;
43b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.preference.PreferenceManager;
44b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.provider.MediaStore;
45b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.provider.MediaStore.Video;
46b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.text.format.DateFormat;
47b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.util.Log;
48b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.KeyEvent;
49b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Menu;
50b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.MenuItem;
51d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport android.view.MenuItem.OnMenuItemClickListener;
52b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.SurfaceHolder;
53b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.View;
54b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Window;
55b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.WindowManager;
56b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.AlphaAnimation;
57b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.Animation;
58b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.ImageView;
59b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.TextView;
60b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.Toast;
61b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
62d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.io.File;
63d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.io.FileDescriptor;
64d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.io.IOException;
65d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.text.SimpleDateFormat;
66d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.util.ArrayList;
67d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.util.Date;
68d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
69b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpublic class VideoCamera extends Activity implements View.OnClickListener,
70d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback,
71d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener {
72b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
73b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final String TAG = "videocamera";
74b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
75b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int CLEAR_SCREEN_DELAY = 4;
76b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int UPDATE_RECORD_TIME = 5;
77b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
78b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int SCREEN_DELAY = 2 * 60 * 1000;
79b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
80b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final long NO_STORAGE_ERROR = -1L;
81b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final long CANNOT_STAT_ERROR = -2L;
82b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final long LOW_STORAGE_THRESHOLD = 512L * 1024L;
83e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    private static final long SHARE_FILE_LENGTH_LIMIT = 3L * 1024L * 1024L;
84b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
859a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private static final int STORAGE_STATUS_OK = 0;
869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private static final int STORAGE_STATUS_LOW = 1;
879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private static final int STORAGE_STATUS_NONE = 2;
889a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
89b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SETTINGS = 6;
90b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_PHOTOS = 7;
91b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_VIDEOS = 8;
92b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_GALLERY_PHOTO = 34;
93b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_PLAY_VIDEO = 35;
94b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_SELECT_VIDEO = 36;
95b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_NEW_VIDEO = 37;
96b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
97b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    SharedPreferences mPreferences;
98b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
99b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final float VIDEO_ASPECT_RATIO = 176.0f / 144.0f;
100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    VideoPreview mVideoPreview;
101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    SurfaceHolder mSurfaceHolder = null;
102b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    ImageView mVideoFrame;
1039bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
1049bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private boolean mIsVideoCaptureIntent;
1059bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // mLastPictureButton and mThumbController
1069bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // are non-null only if isVideoCaptureIntent() is true;
107de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    private ImageView mLastPictureButton;
1089bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private ThumbnailController mThumbController;
109b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1108d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    private static final int MAX_RECORDING_DURATION_MS = 10 * 60 * 1000;
1118d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
1129a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private int mStorageStatus = STORAGE_STATUS_OK;
1139a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
114b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private MediaRecorder mMediaRecorder;
115b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mMediaRecorderRecording = false;
116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mRecordingStartTime;
117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // The video file that the hardware camera is about to record into
118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // (or is recording into.)
119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private String mCameraVideoFilename;
120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private FileDescriptor mCameraVideoFileDescriptor;
121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // The video file that has already been recorded, and that is being
123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // examined by the user.
124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private String mCurrentVideoFilename;
1258d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    private long mCurrentVideoFileLength = 0L;
126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Uri mCurrentVideoUri;
127b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ContentValues mCurrentVideoValues;
128b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
129b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    boolean mPausing = false;
130b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
131d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private ContentResolver mContentResolver;
132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    int mCurrentZoomIndex = 0;
134b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
135b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ShutterButton mShutterButton;
136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private TextView mRecordingTimeView;
1378d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    private boolean mRecordingTimeCountsDown = false;
138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    ArrayList<MenuItem> mGalleryItems = new ArrayList<MenuItem>();
140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    View mPostPictureAlert;
142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    LocationManager mLocationManager = null;
143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Handler mHandler = new MainHandler();
145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
146d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    // This Handler is used to post message back onto the main thread of the
147d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    // application
148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class MainHandler extends Handler {
149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
150b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void handleMessage(Message msg) {
151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            switch (msg.what) {
152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case CLEAR_SCREEN_DELAY: {
154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    clearScreenOnFlag();
155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case UPDATE_RECORD_TIME: {
159d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    updateRecordingTime();
160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                default:
164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.v(TAG, "Unhandled message: " + msg.what);
165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                  break;
166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
167b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
168b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
169b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
170b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onReceive(Context context, Intent intent) {
173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            String action = intent.getAction();
174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (action.equals(Intent.ACTION_MEDIA_EJECT)) {
1759a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(false);
176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                stopVideoRecording();
177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                initializeVideo();
178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
1799a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(true);
180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                initializeVideo();
181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // SD card unavailable
1839a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                // handled in ACTION_MEDIA_EJECT
184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) {
185d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Toast.makeText(VideoCamera.this,
186d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        getResources().getString(R.string.wait), 5000);
187b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) {
1889a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(true);
189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
193d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private static String createName(long dateTaken) {
194b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString();
195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /** Called with the activity is first created. */
198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onCreate(Bundle icicle) {
200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreate(icicle);
201b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
202d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mLocationManager = (LocationManager) getSystemService(
203d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Context.LOCATION_SERVICE);
204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mContentResolver = getContentResolver();
207b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        //setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        requestWindowFeature(Window.FEATURE_PROGRESS);
210b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setContentView(R.layout.video_camera);
211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoPreview = (VideoPreview) findViewById(R.id.camera_preview);
213b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoPreview.setAspectRatio(VIDEO_ASPECT_RATIO);
214b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
215b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // don't set mSurfaceHolder here. We have it set ONLY within
216b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // surfaceCreated / surfaceDestroyed, other parts of the code
217b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // assume that when it is set, the surface is also set.
218b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SurfaceHolder holder = mVideoPreview.getHolder();
219b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.addCallback(this);
220b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
221b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
222b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPostPictureAlert = findViewById(R.id.post_picture_panel);
223b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] ids = new int[]{R.id.play, R.id.share, R.id.discard,
225b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                R.id.cancel, R.id.attach};
226b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int id : ids) {
227b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            findViewById(id).setOnClickListener(this);
228b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
229b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
230b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton = (ShutterButton) findViewById(R.id.shutter_button);
231b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setOnShutterButtonListener(this);
232b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mRecordingTimeView = (TextView) findViewById(R.id.recording_time);
233b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoFrame = (ImageView) findViewById(R.id.video_frame);
2349bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mIsVideoCaptureIntent = isVideoCaptureIntent();
2359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
236d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mLastPictureButton = (ImageView) findViewById(
237d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    R.id.last_picture_button);
2389bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setOnClickListener(this);
239d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            Drawable frame = getResources().getDrawable(
240d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    R.drawable.frame_thumbnail);
2419bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController = new ThumbnailController(mLastPictureButton,
2429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    frame, mContentResolver);
2439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.loadData(ImageManager.getLastVideoThumbPath());
2449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
245b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
246b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
247e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    private void startShareVideoActivity() {
2488d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        if (mCurrentVideoFileLength > SHARE_FILE_LENGTH_LIMIT) {
249e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            Toast.makeText(VideoCamera.this,
250e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                    R.string.too_large_to_attach, Toast.LENGTH_LONG).show();
251e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            return;
252e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
253e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        Intent intent = new Intent();
254e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.setAction(Intent.ACTION_SEND);
255e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.setType("video/3gpp");
256e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.putExtra(Intent.EXTRA_STREAM, mCurrentVideoUri);
257e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        try {
258d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            startActivity(Intent.createChooser(
259d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    intent, getText(R.string.sendVideo)));
260e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        } catch (android.content.ActivityNotFoundException ex) {
261d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            Toast.makeText(VideoCamera.this, R.string.no_way_to_share_video,
262d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    Toast.LENGTH_SHORT).show();
263e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
264e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    }
265e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project
266b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onClick(View v) {
267b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (v.getId()) {
268b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
269b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.gallery:
270b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                MenuHelper.gotoCameraVideoGallery(this);
271b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
272b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
273b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.attach:
274b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doReturnToCaller(true);
275b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
276b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
277b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.cancel:
278b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doReturnToCaller(false);
279b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
280b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
281b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.discard: {
2827638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                Runnable deleteCallback = new Runnable() {
2837638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                    public void run() {
2847638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                        discardCurrentVideoAndStartPreview();
2857638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                    }
2867638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                };
2877638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                MenuHelper.deleteVideo(this, deleteCallback);
288b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
289b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
290b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
291b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.share: {
292e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                startShareVideoActivity();
293b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
294b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
295b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
296b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.play: {
297b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doPlayCurrentVideo();
298b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
300de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
301de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            case R.id.last_picture_button: {
3029bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndShowAlert();
303de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                break;
304de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            }
305b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
306b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
307b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
308b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onShutterButtonFocus(ShutterButton button, boolean pressed) {
309de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        // Do nothing (everything happens in onShutterButtonClick).
310de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
311de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
312de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    public void onShutterButtonClick(ShutterButton button) {
313b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (button.getId()) {
314b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.shutter_button:
315de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                if (mMediaRecorderRecording) {
3169bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    if (mIsVideoCaptureIntent) {
317de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                        stopVideoRecordingAndShowAlert();
318b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } else {
3199bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        stopVideoRecordingAndGetThumbnail();
3209bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        initializeVideo();
3219bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    }
3229bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                } else if (isAlertVisible()) {
3239bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    if (mIsVideoCaptureIntent) {
3249bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        discardCurrentVideoAndStartPreview();
3259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    } else {
3269bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        hideAlertAndStartVideoRecording();
327b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
328de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                } else {
329de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    startVideoRecording();
330b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
331b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
333b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
334b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
335b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doPlayCurrentVideo() {
336b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.e(TAG, "Playing current video: " + mCurrentVideoUri);
337b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri);
338b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
339b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            startActivity(intent);
340b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (android.content.ActivityNotFoundException ex) {
341b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex);
342b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
343b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
344b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
345b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void discardCurrentVideoAndStartPreview() {
346b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        deleteCurrentVideo();
3479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlertAndStartPreview();
348b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
349b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
350b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private OnScreenHint mStorageHint;
351b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3529a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private void updateAndShowStorageHint(boolean mayHaveSd) {
3539a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mStorageStatus = getStorageStatus(mayHaveSd);
3549a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        showStorageHint();
3559a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    }
3569a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
3579a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private void showStorageHint() {
358b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String errorMessage = null;
3599a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        switch (mStorageStatus) {
3609a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        case STORAGE_STATUS_NONE:
361b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            errorMessage = getString(R.string.no_storage);
3629a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            break;
3639a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        case STORAGE_STATUS_LOW:
364b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            errorMessage = getString(R.string.spaceIsLow_content);
365b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
366b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (errorMessage != null) {
367b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStorageHint == null) {
368b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint = OnScreenHint.makeText(this, errorMessage);
369b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
370b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint.setText(errorMessage);
371b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
372b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.show();
373b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else if (mStorageHint != null) {
374b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
375b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
376b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
377b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
378b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3799a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private int getStorageStatus(boolean mayHaveSd) {
3809a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        long remaining = mayHaveSd ? getAvailableStorage() : NO_STORAGE_ERROR;
3819a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (remaining == NO_STORAGE_ERROR) {
3829a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            return STORAGE_STATUS_NONE;
3839a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
3849a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        return remaining < LOW_STORAGE_THRESHOLD
3859a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                ? STORAGE_STATUS_LOW : STORAGE_STATUS_OK;
3869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    }
3879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
388b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
389b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onResume() {
390b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onResume();
391b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
392b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutLong();
393b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
394b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPausing = false;
395b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // install an intent filter to receive SD card related events.
397d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        IntentFilter intentFilter =
398d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
399b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_EJECT);
400b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
401b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
402b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
403b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addDataScheme("file");
404b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        registerReceiver(mReceiver, intentFilter);
4059a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mStorageStatus = getStorageStatus(true);
4069a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
4079a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mHandler.postDelayed(new Runnable() {
4089a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            public void run() {
4099a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                showStorageHint();
4109a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            }
4119a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }, 200);
412b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4139bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        initializeVideo();
414b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
415b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
416b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
417b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onStop() {
418b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutSystemDefault();
419b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onStop();
420b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
421b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
422b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
423b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    protected void onPause() {
424b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPause();
425b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4269bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // This is similar to what mShutterButton.performClick() does,
4279bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // but not quite the same.
4289bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mMediaRecorderRecording) {
4299bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (mIsVideoCaptureIntent) {
4309bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndShowAlert();
4319bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            } else {
4329bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndGetThumbnail();
4339bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            }
4349bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } else {
4359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            stopVideoRecording();
4369bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
437b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
438b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPausing = true;
439b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4409c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        unregisterReceiver(mReceiver);
441b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutSystemDefault();
442b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
4449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.storeData(ImageManager.getLastVideoThumbPath());
4459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
446095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin
447b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mStorageHint != null) {
448b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
449b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
450b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
452b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
453b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
454b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
455b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutLong();
456b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
457b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (keyCode) {
458b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_BACK:
459b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mMediaRecorderRecording) {
460de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
461b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
462d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                } else if (isAlertVisible()) {
4639bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    hideAlertAndStartPreview();
464b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
465b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
466b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
467b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_CAMERA:
468b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
469de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
470b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
471b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
472de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                break;
473b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_CENTER:
474b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
475de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
476de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    return true;
477b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
478b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
479b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_MENU:
480b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mMediaRecorderRecording) {
481de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
482b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
483b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
484b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
485b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
486b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
487b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyDown(keyCode, event);
488b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
489b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
490b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
491b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
492b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch(keyCode) {
493b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case KeyEvent.KEYCODE_CAMERA:
494b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mShutterButton.setPressed(false);
495b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return true;
496b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
497b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyUp(keyCode, event);
498b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
499b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
500b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
501314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber        if (mPausing) {
502314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // We're pausing, the screen is off and we already stopped
503314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // video recording. We don't want to start the camera again
504314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // in this case in order to conserve power.
505314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // The fact that surfaceChanged is called _after_ an onPause appears
506314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // to be legitimate since in that case the lockscreen always returns
507314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // to portrait orientation possibly triggering the notification.
508314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            return;
509314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber        }
510314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber
511b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopVideoRecording();
512b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        initializeVideo();
513b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
514b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
515b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceCreated(SurfaceHolder holder) {
516b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = holder;
517b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
518b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
519b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceDestroyed(SurfaceHolder holder) {
520b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = null;
521b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
522b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
523b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    void gotoGallery() {
524b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.gotoCameraVideoGallery(this);
525b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
526b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
527b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
528b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onPrepareOptionsMenu(Menu menu) {
529b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPrepareOptionsMenu(menu);
530b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
531b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int i = 1; i <= MenuHelper.MENU_ITEM_MAX; i++) {
532b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (i != MenuHelper.GENERIC_ITEM) {
533b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                menu.setGroupVisible(i, false);
534b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
535b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
536b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
537b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        menu.setGroupVisible(MenuHelper.VIDEO_MODE_ITEM, true);
538b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
539b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
540b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
541b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
542b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onCreateOptionsMenu(Menu menu) {
543b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreateOptionsMenu(menu);
544b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent) {
546b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // No options menu for attach mode.
547b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
548b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
549b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            addBaseMenuItems(menu);
550d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int menuFlags = MenuHelper.INCLUDE_ALL
551d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    & ~MenuHelper.INCLUDE_ROTATE_MENU
552095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin                    & ~MenuHelper.INCLUDE_DETAILS_MENU;
553b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            MenuHelper.addImageMenuItems(
554b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    menu,
555095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin                    menuFlags,
556b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    false,
557b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    VideoCamera.this,
558b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mHandler,
559b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
560b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // Handler for deletion
561b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    new Runnable() {
562b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run() {
563b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            // What do we do here?
564b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            // mContentResolver.delete(uri, null, null);
565b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
566b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    },
567b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    new MenuHelper.MenuInvoker() {
568b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run(final MenuHelper.MenuCallback cb) {
569b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
570b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    });
571b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
572d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.IMAGE_SAVING_ITEM,
573d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_SAVE_GALLERY_PHOTO, 0,
574d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    R.string.camera_gallery_photos_text)
575d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(
576d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    new MenuItem.OnMenuItemClickListener() {
577d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
578d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
579d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
580d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
581d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
582b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
583b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
584b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
585b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean isVideoCaptureIntent() {
588b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String action = getIntent().getAction();
589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action));
590b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
591b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
592b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doReturnToCaller(boolean success) {
593b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent resultIntent = new Intent();
594b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int resultCode;
595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (success) {
596b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultCode = RESULT_OK;
597b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultIntent.setData(mCurrentVideoUri);
598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultCode = RESULT_CANCELED;
600b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setResult(resultCode, resultIntent);
602b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        finish();
603b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
604b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
605b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
606b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * Returns
607b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * @return number of bytes available, or an ERROR code.
608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
609b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static long getAvailableStorage() {
610b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
611b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (!ImageManager.hasStorage()) {
612b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return NO_STORAGE_ERROR;
613b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
614d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                String storageDirectory = Environment
615d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        .getExternalStorageDirectory().toString();
616b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                StatFs stat = new StatFs(storageDirectory);
617d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                return ((long) stat.getAvailableBlocks()
618d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        * (long) stat.getBlockSize());
619b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
620b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (Exception ex) {
621b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // if we can't stat the filesystem then we don't know how many
622b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // free bytes exist.  It might be zero but just leave it
623b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // blank since we really don't know.
624b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return CANNOT_STAT_ERROR;
625b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
626b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
628b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void cleanupEmptyFile() {
629b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraVideoFilename != null) {
630b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            File f = new File(mCameraVideoFilename);
631b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (f.length() == 0 && f.delete()) {
632b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project              Log.v(TAG, "Empty video file deleted: " + mCameraVideoFilename);
633b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project              mCameraVideoFilename = null;
634b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
635b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
636b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
637b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6389bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // initializeVideo() starts preview and prepare media recorder.
639b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // Returns false if initializeVideo fails
640b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean initializeVideo() {
641b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "initializeVideo");
6429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
6439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // We will call initializeVideo() again when the alert is hidden.
6449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (isAlertVisible()) return false;
6459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
646b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent intent = getIntent();
647b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bundle myExtras = intent.getExtras();
648b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent && myExtras != null) {
650b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
651b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (saveUri != null) {
652b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
653b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCameraVideoFileDescriptor = mContentResolver.
654b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        openFileDescriptor(saveUri, "rw").getFileDescriptor();
655b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCurrentVideoUri = saveUri;
656d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                } catch (java.io.FileNotFoundException ex) {
657b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // invalid uri
658b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.e(TAG, ex.toString());
659b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
660b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
661b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
662b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        releaseMediaRecorder();
663b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mSurfaceHolder == null) {
665b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "SurfaceHolder is null");
666b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
667b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
668b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder = new MediaRecorder();
670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
671d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
672b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
673b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
674b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6758d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        mMediaRecorder.setMaxDuration(MAX_RECORDING_DURATION_MS);
6768d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
6779a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (mStorageStatus != STORAGE_STATUS_OK) {
678b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.setOutputFile("/dev/null");
679b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
680d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // We try Uri in intent first. If it doesn't work, use our own
681d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // instead.
682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCameraVideoFileDescriptor != null) {
683b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOutputFile(mCameraVideoFileDescriptor);
684b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
685b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                createVideoPath();
686b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOutputFile(mCameraVideoFilename);
687b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
688b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
689b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
690d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        boolean videoQualityHigh = getBooleanPreference(
691d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                CameraSettings.KEY_VIDEO_QUALITY,
692b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                CameraSettings.DEFAULT_VIDEO_QUALITY_VALUE);
693b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
694b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) {
695d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int extraVideoQuality = intent.getIntExtra(
696d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MediaStore.EXTRA_VIDEO_QUALITY, 0);
697b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            videoQualityHigh = (extraVideoQuality > 0);
698b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
699b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
700b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // Use the same frame rate for both, since internally
701b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // if the frame rate is too large, it can cause camera to become
702b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // unstable. We need to fix the MediaRecorder to disable the support
703b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // of setting frame rate for now.
704b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoFrameRate(20);
705b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (videoQualityHigh) {
706d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mMediaRecorder.setVideoSize(352, 288);
707b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
708d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mMediaRecorder.setVideoSize(176, 144);
709b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
710b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
711d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
712b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
713de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
714de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        long remaining = getAvailableStorage();
715de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        // remaining >= LOW_STORAGE_THRESHOLD at this point, reserve a quarter
716d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // of that to make it more likely that recording can complete
717d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // successfully.
718de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        try {
719d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mMediaRecorder.setMaxFileSize(remaining -
720d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    LOW_STORAGE_THRESHOLD / 4);
721de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        } catch (RuntimeException exception) {
722de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // We are going to ignore failure of setMaxFileSize here, as
723de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // a) The composer selected may simply not support it, or
724de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // b) The underlying media framework may not handle 64-bit range
725de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            //    on the size restriction.
726de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        }
727de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
728b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
729b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.prepare();
730b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (IOException exception) {
731b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "prepare failed for " + mCameraVideoFilename);
732b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            releaseMediaRecorder();
733b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // TODO: add more exception handling logic here
734b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
735b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
736b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorderRecording = false;
7379bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
7389bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent && !mThumbController.isUriValid()) {
7399bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            updateLastVideo();
7409bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
7419bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
7429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
7439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.updateDisplayIfNeeded();
7449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
7459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
746b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
747b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
748b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
749b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void releaseMediaRecorder() {
750b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Releasing media recorder.");
751b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mMediaRecorder != null) {
752b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cleanupEmptyFile();
753b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.reset();
754b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.release();
755b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder = null;
756b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
757b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
758b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
759b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int getIntPreference(String key, int defaultValue) {
760b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String s = mPreferences.getString(key, "");
761b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int result = defaultValue;
762b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
763b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            result = Integer.parseInt(s);
764b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (NumberFormatException e) {
765b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Ignore, result is already the default value.
766b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
767b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return result;
768b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
769b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
770b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean getBooleanPreference(String key, boolean defaultValue) {
771b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return getIntPreference(key, defaultValue ? 1 : 0) != 0;
772b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
773b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
774b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void createVideoPath() {
775b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        long dateTaken = System.currentTimeMillis();
776b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String title = createName(dateTaken);
777b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String displayName = title + ".3gp"; // Used when emailing.
778b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME;
779b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        File cameraDir = new File(cameraDirPath);
780b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        cameraDir.mkdirs();
781b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SimpleDateFormat dateFormat = new SimpleDateFormat(
782b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                getString(R.string.video_file_name_format));
783b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Date date = new Date(dateTaken);
784b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String filepart = dateFormat.format(date);
785b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String filename = cameraDirPath + "/" + filepart + ".3gp";
786b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ContentValues values = new ContentValues(7);
787b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.TITLE, title);
788b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DISPLAY_NAME, displayName);
789b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DESCRIPTION, "");
790b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DATE_TAKEN, dateTaken);
791b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.MIME_TYPE, "video/3gpp");
792b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DATA, filename);
793b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFilename = filename;
794b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Current camera video filename: " + mCameraVideoFilename);
795b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCurrentVideoValues = values;
796b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
797b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
798b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void registerVideo() {
799b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraVideoFileDescriptor == null) {
800b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri videoTable = Uri.parse("content://media/external/video/media");
801b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoUri = mContentResolver.insert(videoTable,
802b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCurrentVideoValues);
803b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "Current video URI: " + mCurrentVideoUri);
804b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
805b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCurrentVideoValues = null;
806b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
807b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
808b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void deleteCurrentVideo() {
809b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCurrentVideoFilename != null) {
810b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            deleteVideoFile(mCurrentVideoFilename);
811b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoFilename = null;
812b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
813b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCurrentVideoUri != null) {
814b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mContentResolver.delete(mCurrentVideoUri, null, null);
815b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoUri = null;
816b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
817de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        updateAndShowStorageHint(true);
818b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
819b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
820b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void deleteVideoFile(String fileName) {
821b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Deleting video " + fileName);
822b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        File f = new File(fileName);
823d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (!f.delete()) {
824b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "Could not delete " + fileName);
825b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
826b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
827b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
828b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void addBaseMenuItems(Menu menu) {
829b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.addSwitchModeMenuItem(menu, this, false);
830b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
831d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.IMAGE_MODE_ITEM,
832d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_GALLERY_PHOTOS, 0, R.string.camera_gallery_photos_text)
833d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
834d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
835d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
836d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
837d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
838d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
839b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
840b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
841b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
842b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
843d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.VIDEO_MODE_ITEM,
844d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_GALLERY_VIDEOS, 0, R.string.camera_gallery_photos_text)
845d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
846d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
847d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
848d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
849d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
850d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
851b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
852b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
853b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
854b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
855d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        MenuItem item = menu.add(MenuHelper.GENERIC_ITEM, MENU_SETTINGS, 0,
856d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                R.string.settings)
857d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                .setOnMenuItemClickListener(new OnMenuItemClickListener() {
858d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    public boolean onMenuItemClick(MenuItem item) {
859d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        Intent intent = new Intent();
860d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        intent.setClass(VideoCamera.this, CameraSettings.class);
861d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        startActivity(intent);
862d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        return true;
863d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    }
864d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                });
865b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        item.setIcon(android.R.drawable.ic_menu_preferences);
866b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
867b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
868b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // from MediaRecorder.OnErrorListener
869b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onError(MediaRecorder mr, int what, int extra) {
870b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) {
871b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // We may have run out of space on the sdcard.
872b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            stopVideoRecording();
8739a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            updateAndShowStorageHint(true);
874b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
875b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
876b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
8778d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    // from MediaRecorder.OnInfoListener
8788d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    public void onInfo(MediaRecorder mr, int what, int extra) {
8798d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
880de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            mShutterButton.performClick();
881d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        } else if (what
882d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
883de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            mShutterButton.performClick();
884de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            updateAndShowStorageHint(true);
8858d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        }
8868d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    }
8878d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
8889c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    /*
8899c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     * Make sure we're not recording music playing in the background, ask
8909c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     * the MediaPlaybackService to pause playback.
8919c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     */
8929c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private void pauseAudioPlayback() {
8939c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // Shamelessly copied from MediaPlaybackService.java, which
8949c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // should be public, but isn't.
8959c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        Intent i = new Intent("com.android.music.musicservicecommand");
8969c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        i.putExtra("command", "pause");
8979c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
8989c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        sendBroadcast(i);
8999c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    }
9009c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
901b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void startVideoRecording() {
902b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "startVideoRecording");
903b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (!mMediaRecorderRecording) {
904b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
9059a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            if (mStorageStatus != STORAGE_STATUS_OK) {
906b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "Storage issue, ignore the start request");
907b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
908b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
909b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
910b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Check mMediaRecorder to see whether it is initialized or not.
911d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            if (mMediaRecorder == null && initializeVideo() == false) {
912b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Initialize video (MediaRecorder) failed.");
913b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
914b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
915b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
9169c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            pauseAudioPlayback();
9179c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
918b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
919b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOnErrorListener(this);
9208d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                mMediaRecorder.setOnInfoListener(this);
921b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.start();   // Recording is now started
922b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (RuntimeException e) {
923b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Could not start media recorder. ", e);
924b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
925b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
926b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorderRecording = true;
927b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingStartTime = SystemClock.uptimeMillis();
928b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateRecordingIndicator(true);
929b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setText("");
930b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setVisibility(View.VISIBLE);
931b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mHandler.sendEmptyMessage(UPDATE_RECORD_TIME);
932b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setScreenTimeoutInfinite();
933de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            hideLastPictureButton();
934b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
935b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
936b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
937b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateRecordingIndicator(boolean showRecording) {
938d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        int drawableId = showRecording
939d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                ? R.drawable.ic_camera_bar_indicator_record
940d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                : R.drawable.ic_camera_indicator_video;
941b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Drawable drawable = getResources().getDrawable(drawableId);
942b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setImageDrawable(drawable);
943b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
944b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
9459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void stopVideoRecordingAndGetThumbnail() {
9469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        stopVideoRecording();
9479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        acquireVideoThumb();
948b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
949b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
950de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    private void stopVideoRecordingAndShowAlert() {
951de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        stopVideoRecording();
9529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        showAlert();
953de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
954de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
9559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void showAlert() {
956b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] pickIds = {R.id.attach, R.id.cancel};
957b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] normalIds = {R.id.gallery, R.id.share, R.id.discard};
958b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] alwaysOnIds = {R.id.play};
959b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] hideIds = pickIds;
960b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] connectIds = normalIds;
9619bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent) {
962b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            hideIds = normalIds;
963b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            connectIds = pickIds;
964b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
965d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        for (int id : hideIds) {
966b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostPictureAlert.findViewById(id).setVisibility(View.GONE);
967b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
9688d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        ActionMenuButton shareButton =
9698d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                (ActionMenuButton) mPostPictureAlert.findViewById(R.id.share);
9708d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        shareButton.setRestricted(
9718d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                mCurrentVideoFileLength > SHARE_FILE_LENGTH_LIMIT);
972b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        connectAndFadeIn(connectIds);
973b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        connectAndFadeIn(alwaysOnIds);
974de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        hideLastPictureButton();
975b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPostPictureAlert.setVisibility(View.VISIBLE);
9769bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
9779bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // There are two cases we are here:
9789bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // (1) We are in a capture video intent, and we are reviewing the video
979095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin        //     we just taken.
9809bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // (2) The thumbnail button is clicked: we review the video associated
9819bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        //     with the thumbnail.
9829bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // For the second case, we copy the associated URI and filename to
9839bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // mCurrentVideoUri and mCurrentVideoFilename, so the video frame shown
9849bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // and the target for actions (play, delete, ...) will be correct.
9859bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
9869bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
9879bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mCurrentVideoUri = mThumbController.getUri();
9889bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mCurrentVideoFilename = getDataPath(mCurrentVideoUri);
9899bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
9909bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
9919bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        String path = mCurrentVideoFilename;
9929bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (path != null) {
993101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            Bitmap videoFrame = Util.createVideoThumbnail(path);
9949bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mVideoFrame.setImageBitmap(videoFrame);
9959bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mVideoFrame.setVisibility(View.VISIBLE);
9969bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
997b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
998b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
9999bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlert() {
1000de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mVideoFrame.setVisibility(View.INVISIBLE);
1001de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mPostPictureAlert.setVisibility(View.INVISIBLE);
1002de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        showLastPictureButton();
1003de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1004de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
1005b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void connectAndFadeIn(int[] connectIds) {
1006d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        for (int id : connectIds) {
1007b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            View view = mPostPictureAlert.findViewById(id);
1008b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            view.setOnClickListener(this);
1009b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Animation animation = new AlphaAnimation(0F, 1F);
1010b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            animation.setDuration(500);
10119bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            view.startAnimation(animation);
1012b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1013b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1014b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10159bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private boolean isAlertVisible() {
1016b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return mPostPictureAlert.getVisibility() == View.VISIBLE;
1017b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1018b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1019b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void stopVideoRecording() {
1020b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "stopVideoRecording");
1021b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean needToRegisterRecording = false;
1022b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mMediaRecorderRecording || mMediaRecorder != null) {
1023b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mMediaRecorderRecording && mMediaRecorder != null) {
1024b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
1025b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mMediaRecorder.setOnErrorListener(null);
10268d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    mMediaRecorder.setOnInfoListener(null);
1027b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mMediaRecorder.stop();
1028b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } catch (RuntimeException e) {
1029b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.e(TAG, "stop fail: " + e.getMessage());
1030b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
10318d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
1032b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCurrentVideoFilename = mCameraVideoFilename;
10338d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                try {
1034d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    mCurrentVideoFileLength =
1035d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            new File(mCurrentVideoFilename).length();
10368d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                } catch (RuntimeException e) {
10378d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    Log.e(TAG, "get file length fail: " + e.getMessage());
10388d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    mCurrentVideoFileLength = 0;
10398d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                }
1040d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Log.v(TAG, "Setting current video filename: "
1041d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        + mCurrentVideoFilename);
1042b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                needToRegisterRecording = true;
1043b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorderRecording = false;
1044b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1045b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            releaseMediaRecorder();
1046b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateRecordingIndicator(false);
1047b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setVisibility(View.GONE);
1048b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setScreenTimeoutLong();
1049b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
10509a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (needToRegisterRecording && mStorageStatus == STORAGE_STATUS_OK) {
10519a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            registerVideo();
10529a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
1053b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1054b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFilename = null;
1055b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFileDescriptor = null;
1056b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1057b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1058b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutSystemDefault() {
1059b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1060b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        clearScreenOnFlag();
1061b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1062b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1063b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutLong() {
1064b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1065b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenOnFlag();
1066b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
1067b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1068b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1069b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutInfinite() {
1070b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1071b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenOnFlag();
1072b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1073b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1074b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void clearScreenOnFlag() {
1075b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window w = getWindow();
1076d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1077d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if ((w.getAttributes().flags & flag) != 0) {
1078d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            w.clearFlags(flag);
1079b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1080b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1081b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1082b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenOnFlag() {
1083b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window w = getWindow();
1084d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1085d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if ((w.getAttributes().flags & flag) == 0) {
1086d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            w.addFlags(flag);
1087b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1088b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1089b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10909bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlertAndStartPreview() {
10919bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlert();
10929bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        initializeVideo();
1093b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1094b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10959bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlertAndStartVideoRecording() {
10969bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlert();
10979bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        startVideoRecording();
1098b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1099b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11009bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void acquireVideoThumb() {
1101101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        Bitmap videoFrame = Util.createVideoThumbnail(mCurrentVideoFilename);
11029bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mThumbController.setData(mCurrentVideoUri, videoFrame);
1103de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1104de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
11059bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void showLastPictureButton() {
11069bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
11079bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setVisibility(View.VISIBLE);
1108de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        }
11099bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    }
1110de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
11119bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideLastPictureButton() {
11129bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
11139bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setVisibility(View.INVISIBLE);
11149bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
1115de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1116de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
11179bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static ImageManager.DataLocation dataLocation() {
11189bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        return ImageManager.DataLocation.EXTERNAL;
1119de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1120de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
11219bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void updateLastVideo() {
1122101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        IImageList list = ImageManager.instance().allImages(
11239bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            this,
11249bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mContentResolver,
11259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            dataLocation(),
11269bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.INCLUDE_VIDEOS,
11279bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.SORT_ASCENDING,
11289bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.CAMERA_IMAGE_BUCKET_ID);
11299bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        int count = list.getCount();
11309bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (count > 0) {
1131d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            IImage image = list.getImageAt(count - 1);
11329bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            Uri uri = image.fullSizeImageUri();
11339bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(uri, image.miniThumbBitmap());
11349bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } else {
11359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(null, null);
11369bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
11379bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        list.deactivate();
1138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11409bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static final String[] DATA_PATH_PROJECTION = new String[] {
11419bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        "_data"
11429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    };
11439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
11449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private String getDataPath(Uri uri) {
11459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        Cursor c = null;
11469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        try {
1147d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            c = mContentResolver.query(uri, DATA_PATH_PROJECTION, null, null,
1148d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    null);
11499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (c != null && c.moveToFirst()) {
11509bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                return c.getString(0);
11519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            } else {
11529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                return null;
11539bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            }
11549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } finally {
11559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (c != null) c.close();
1156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1158d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1159d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private void updateRecordingTime() {
1160d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (!mMediaRecorderRecording) return;
1161d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long now = SystemClock.uptimeMillis();
1162d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long delta = now - mRecordingStartTime;
1163d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1164d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // Starting a minute before reaching the max duration
1165d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // limit, we'll countdown the remaining time instead.
1166d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        boolean countdownRemainingTime =
1167d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            (delta >= MAX_RECORDING_DURATION_MS - 60000);
1168d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1169d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (countdownRemainingTime) {
1170d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            delta = Math.max(0, MAX_RECORDING_DURATION_MS - delta);
1171d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1172d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1173d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long seconds = (delta + 500) / 1000;  // round to nearest
1174d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long minutes = seconds / 60;
1175d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long hours = minutes / 60;
1176d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long remainderMinutes = minutes - (hours * 60);
1177d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long remainderSeconds = seconds - (minutes * 60);
1178d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1179d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String secondsString = Long.toString(remainderSeconds);
1180d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (secondsString.length() < 2) {
1181d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            secondsString = "0" + secondsString;
1182d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1183d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String minutesString = Long.toString(remainderMinutes);
1184d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (minutesString.length() < 2) {
1185d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            minutesString = "0" + minutesString;
1186d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1187d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String text = minutesString + ":" + secondsString;
1188d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (hours > 0) {
1189d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            String hoursString = Long.toString(hours);
1190d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            if (hoursString.length() < 2) {
1191d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                hoursString = "0" + hoursString;
1192d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            }
1193d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            text = hoursString + ":" + text;
1194d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1195d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mRecordingTimeView.setText(text);
1196d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1197d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (mRecordingTimeCountsDown != countdownRemainingTime) {
1198d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // Avoid setting the color on every update, do it only
1199d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // when it needs changing.
1200d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1201d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mRecordingTimeCountsDown = countdownRemainingTime;
1202d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1203d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int color = getResources().getColor(
1204d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    countdownRemainingTime
1205d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    ? R.color.recording_time_remaining_text
1206d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    : R.color.recording_time_elapsed_text);
1207d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1208d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mRecordingTimeView.setTextColor(color);
1209d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1210d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1211d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // Work around a limitation of the T-Mobile G1: The T-Mobile
1212d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // hardware blitter can't pixel-accurately scale and clip at the
1213d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // same time, and the SurfaceFlinger doesn't attempt to work around
1214d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // this limitation. In order to avoid visual corruption we must
1215d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // manually refresh the entire surface view when changing any
1216d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // overlapping view's contents.
1217d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mVideoPreview.invalidate();
1218d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mHandler.sendEmptyMessageDelayed(UPDATE_RECORD_TIME, 1000);
1219d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    }
1220b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project}
1221