VideoCamera.java revision 937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37
1b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project/*
2b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
4b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * you may not use this file except in compliance with the License.
6b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * You may obtain a copy of the License at
7b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
8b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
10b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * See the License for the specific language governing permissions and
14b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * limitations under the License.
15b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */
16b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
17b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpackage com.android.camera;
18b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
19101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport com.android.camera.gallery.IImage;
20101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport com.android.camera.gallery.IImageList;
21101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
22b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.app.Activity;
23b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.BroadcastReceiver;
24b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.ContentResolver;
25b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.ContentValues;
26b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Context;
27b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Intent;
28b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.IntentFilter;
29b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.SharedPreferences;
30095afa19556bf550262e3cccb9edacc04e6f726aOwen Linimport android.database.Cursor;
31b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.Bitmap;
32b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.drawable.Drawable;
33b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.location.LocationManager;
34b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.media.MediaRecorder;
35b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.net.Uri;
36b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Bundle;
37b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Environment;
38b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Handler;
39b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Message;
40b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.StatFs;
41b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.SystemClock;
42b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.preference.PreferenceManager;
43b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.provider.MediaStore;
44b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.provider.MediaStore.Video;
45b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.text.format.DateFormat;
46b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.util.Log;
47b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.KeyEvent;
48b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Menu;
49b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.MenuItem;
50b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.SurfaceHolder;
51b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.View;
52b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Window;
53b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.WindowManager;
54937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Linimport android.view.MenuItem.OnMenuItemClickListener;
55b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.AlphaAnimation;
56b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.Animation;
57b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.ImageView;
58b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.TextView;
59b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.Toast;
60b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
61d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.io.File;
62d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.io.FileDescriptor;
63d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.io.IOException;
64d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.text.SimpleDateFormat;
65d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.util.ArrayList;
66d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.util.Date;
67d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
6823c51b794e95c201290e36737f379c4bb8eefeaeRay Chen/**
6923c51b794e95c201290e36737f379c4bb8eefeaeRay Chen * The Camcorder activity.
7023c51b794e95c201290e36737f379c4bb8eefeaeRay Chen */
71b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpublic class VideoCamera extends Activity implements View.OnClickListener,
72d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback,
73d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener {
74b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
75b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final String TAG = "videocamera";
76b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
77b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int CLEAR_SCREEN_DELAY = 4;
78b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int UPDATE_RECORD_TIME = 5;
79b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
80b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final int SCREEN_DELAY = 2 * 60 * 1000;
81b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
82b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final long NO_STORAGE_ERROR = -1L;
83b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final long CANNOT_STAT_ERROR = -2L;
84b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final long LOW_STORAGE_THRESHOLD = 512L * 1024L;
85e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    private static final long SHARE_FILE_LENGTH_LIMIT = 3L * 1024L * 1024L;
86b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private static final int STORAGE_STATUS_OK = 0;
889a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private static final int STORAGE_STATUS_LOW = 1;
899a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private static final int STORAGE_STATUS_NONE = 2;
909a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
91b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SETTINGS = 6;
92b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_PHOTOS = 7;
93b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_GALLERY_VIDEOS = 8;
94b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_GALLERY_PHOTO = 34;
95b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_PLAY_VIDEO = 35;
96b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_SELECT_VIDEO = 36;
97b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static final int MENU_SAVE_NEW_VIDEO = 37;
98b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
99b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    SharedPreferences mPreferences;
100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static final float VIDEO_ASPECT_RATIO = 176.0f / 144.0f;
102b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    VideoPreview mVideoPreview;
103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    SurfaceHolder mSurfaceHolder = null;
104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    ImageView mVideoFrame;
1059bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
1069bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private boolean mIsVideoCaptureIntent;
1079bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // mLastPictureButton and mThumbController
1089bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // are non-null only if isVideoCaptureIntent() is true;
109de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    private ImageView mLastPictureButton;
1109bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private ThumbnailController mThumbController;
111b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1128d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    private static final int MAX_RECORDING_DURATION_MS = 10 * 60 * 1000;
1138d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
1149a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private int mStorageStatus = STORAGE_STATUS_OK;
1159a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private MediaRecorder mMediaRecorder;
117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean mMediaRecorderRecording = false;
118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private long mRecordingStartTime;
119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // The video file that the hardware camera is about to record into
120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // (or is recording into.)
121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private String mCameraVideoFilename;
122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private FileDescriptor mCameraVideoFileDescriptor;
123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // The video file that has already been recorded, and that is being
125b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // examined by the user.
126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private String mCurrentVideoFilename;
1278d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    private long mCurrentVideoFileLength = 0L;
128b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Uri mCurrentVideoUri;
129b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ContentValues mCurrentVideoValues;
130b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
131b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    boolean mPausing = false;
132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
133d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private ContentResolver mContentResolver;
134b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
135b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    int mCurrentZoomIndex = 0;
136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
137b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private ShutterButton mShutterButton;
138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private TextView mRecordingTimeView;
1398d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    private boolean mRecordingTimeCountsDown = false;
140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    ArrayList<MenuItem> mGalleryItems = new ArrayList<MenuItem>();
142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    View mPostPictureAlert;
144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    LocationManager mLocationManager = null;
145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private Handler mHandler = new MainHandler();
147b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
148d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    // This Handler is used to post message back onto the main thread of the
149d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    // application
150b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private class MainHandler extends Handler {
151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void handleMessage(Message msg) {
153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            switch (msg.what) {
154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case CLEAR_SCREEN_DELAY: {
156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    clearScreenOnFlag();
157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                case UPDATE_RECORD_TIME: {
161d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    updateRecordingTime();
162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    break;
163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                default:
166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.v(TAG, "Unhandled message: " + msg.what);
167b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                  break;
168b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
169b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
170937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Lin    }
171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        @Override
174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void onReceive(Context context, Intent intent) {
175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            String action = intent.getAction();
176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (action.equals(Intent.ACTION_MEDIA_EJECT)) {
1779a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(false);
178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                stopVideoRecording();
179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                initializeVideo();
180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
1819a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(true);
182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                initializeVideo();
183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                // SD card unavailable
1859a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                // handled in ACTION_MEDIA_EJECT
186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) {
187d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Toast.makeText(VideoCamera.this,
188d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        getResources().getString(R.string.wait), 5000);
189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) {
1909a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                updateAndShowStorageHint(true);
191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
193b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
194b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
195d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private static String createName(long dateTaken) {
196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString();
197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /** Called with the activity is first created. */
200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
201b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onCreate(Bundle icicle) {
202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreate(icicle);
203b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
204d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mLocationManager = (LocationManager) getSystemService(
205d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Context.LOCATION_SERVICE);
206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
207b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mContentResolver = getContentResolver();
209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
210b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        //setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        requestWindowFeature(Window.FEATURE_PROGRESS);
212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setContentView(R.layout.video_camera);
213b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
214b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoPreview = (VideoPreview) findViewById(R.id.camera_preview);
215b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoPreview.setAspectRatio(VIDEO_ASPECT_RATIO);
216b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
217b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // don't set mSurfaceHolder here. We have it set ONLY within
218b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // surfaceCreated / surfaceDestroyed, other parts of the code
219b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // assume that when it is set, the surface is also set.
220b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SurfaceHolder holder = mVideoPreview.getHolder();
221b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.addCallback(this);
222b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
223b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPostPictureAlert = findViewById(R.id.post_picture_panel);
225b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
226b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] ids = new int[]{R.id.play, R.id.share, R.id.discard,
227b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                R.id.cancel, R.id.attach};
228b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int id : ids) {
229b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            findViewById(id).setOnClickListener(this);
230b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
231b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
232b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton = (ShutterButton) findViewById(R.id.shutter_button);
233b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setOnShutterButtonListener(this);
234b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mRecordingTimeView = (TextView) findViewById(R.id.recording_time);
235b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mVideoFrame = (ImageView) findViewById(R.id.video_frame);
2369bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mIsVideoCaptureIntent = isVideoCaptureIntent();
2379bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
238d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mLastPictureButton = (ImageView) findViewById(
239d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    R.id.last_picture_button);
2409bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setOnClickListener(this);
241d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            Drawable frame = getResources().getDrawable(
242d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    R.drawable.frame_thumbnail);
2439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController = new ThumbnailController(mLastPictureButton,
2449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    frame, mContentResolver);
2459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.loadData(ImageManager.getLastVideoThumbPath());
2469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
247b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
248b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
249e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    private void startShareVideoActivity() {
2508d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        if (mCurrentVideoFileLength > SHARE_FILE_LENGTH_LIMIT) {
251e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            Toast.makeText(VideoCamera.this,
252e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                    R.string.too_large_to_attach, Toast.LENGTH_LONG).show();
253e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project            return;
254e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
255e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        Intent intent = new Intent();
256e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.setAction(Intent.ACTION_SEND);
257e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.setType("video/3gpp");
258e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        intent.putExtra(Intent.EXTRA_STREAM, mCurrentVideoUri);
259e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        try {
260d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            startActivity(Intent.createChooser(
261d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    intent, getText(R.string.sendVideo)));
262e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        } catch (android.content.ActivityNotFoundException ex) {
263d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            Toast.makeText(VideoCamera.this, R.string.no_way_to_share_video,
264d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    Toast.LENGTH_SHORT).show();
265e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project        }
266e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project    }
267e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project
268b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onClick(View v) {
269b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (v.getId()) {
270b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
271b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.gallery:
272b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                MenuHelper.gotoCameraVideoGallery(this);
273b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
274b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
275b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.attach:
276b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doReturnToCaller(true);
277b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
278b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
279b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.cancel:
280b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doReturnToCaller(false);
281b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
282b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
283b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.discard: {
2847638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                Runnable deleteCallback = new Runnable() {
2857638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                    public void run() {
2867638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                        discardCurrentVideoAndStartPreview();
2877638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                    }
2887638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                };
2897638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen                MenuHelper.deleteVideo(this, deleteCallback);
290b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
291b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
292b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
293b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.share: {
294e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project                startShareVideoActivity();
295b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
296b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
297b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
298b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.play: {
299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                doPlayCurrentVideo();
300b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
301b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
302de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
303de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            case R.id.last_picture_button: {
3049bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndShowAlert();
305de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                break;
306de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            }
307b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
308b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
309b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
310b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onShutterButtonFocus(ShutterButton button, boolean pressed) {
311de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        // Do nothing (everything happens in onShutterButtonClick).
312de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
313de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
314de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    public void onShutterButtonClick(ShutterButton button) {
315b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (button.getId()) {
316b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case R.id.shutter_button:
317de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                if (mMediaRecorderRecording) {
3189bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    if (mIsVideoCaptureIntent) {
319de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                        stopVideoRecordingAndShowAlert();
320b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    } else {
3219bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        stopVideoRecordingAndGetThumbnail();
3229bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        initializeVideo();
3239bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    }
3249bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                } else if (isAlertVisible()) {
3259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    if (mIsVideoCaptureIntent) {
3269bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        discardCurrentVideoAndStartPreview();
3279bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    } else {
3289bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                        hideAlertAndStartVideoRecording();
329b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    }
330de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                } else {
331de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    startVideoRecording();
332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
333b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
334b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
335b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
336b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
337b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doPlayCurrentVideo() {
338b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.e(TAG, "Playing current video: " + mCurrentVideoUri);
339b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri);
340b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
341b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            startActivity(intent);
342b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (android.content.ActivityNotFoundException ex) {
343b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex);
344b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
345b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
346b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
347b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void discardCurrentVideoAndStartPreview() {
348b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        deleteCurrentVideo();
3499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlertAndStartPreview();
350b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
351b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
352b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private OnScreenHint mStorageHint;
353b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3549a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private void updateAndShowStorageHint(boolean mayHaveSd) {
3559a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mStorageStatus = getStorageStatus(mayHaveSd);
3569a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        showStorageHint();
3579a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    }
3589a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
3599a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private void showStorageHint() {
360b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String errorMessage = null;
3619a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        switch (mStorageStatus) {
3629a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        case STORAGE_STATUS_NONE:
363b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            errorMessage = getString(R.string.no_storage);
3649a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            break;
3659a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        case STORAGE_STATUS_LOW:
366b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            errorMessage = getString(R.string.spaceIsLow_content);
367b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
368b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (errorMessage != null) {
369b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mStorageHint == null) {
370b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint = OnScreenHint.makeText(this, errorMessage);
371b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
372b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mStorageHint.setText(errorMessage);
373b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
374b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.show();
375b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else if (mStorageHint != null) {
376b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
377b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
378b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
379b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
380b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
3819a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    private int getStorageStatus(boolean mayHaveSd) {
3829a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        long remaining = mayHaveSd ? getAvailableStorage() : NO_STORAGE_ERROR;
3839a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (remaining == NO_STORAGE_ERROR) {
3849a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            return STORAGE_STATUS_NONE;
3859a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
3869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        return remaining < LOW_STORAGE_THRESHOLD
3879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                ? STORAGE_STATUS_LOW : STORAGE_STATUS_OK;
3889a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project    }
3899a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
390b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
391b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onResume() {
392b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onResume();
393b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
394b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutLong();
395b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPausing = false;
397b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
398b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // install an intent filter to receive SD card related events.
399d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        IntentFilter intentFilter =
400d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
401b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_EJECT);
402b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
403b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
404b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
405b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        intentFilter.addDataScheme("file");
406b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        registerReceiver(mReceiver, intentFilter);
4079a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mStorageStatus = getStorageStatus(true);
4089a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project
4099a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        mHandler.postDelayed(new Runnable() {
4109a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            public void run() {
4119a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project                showStorageHint();
4129a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            }
4139a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }, 200);
414b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4159bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        initializeVideo();
416b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
417b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
418b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
419b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onStop() {
420b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutSystemDefault();
421b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onStop();
422b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
423b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
424b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
425b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    protected void onPause() {
426b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPause();
427b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4289bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // This is similar to what mShutterButton.performClick() does,
4299bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // but not quite the same.
4309bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mMediaRecorderRecording) {
4319bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (mIsVideoCaptureIntent) {
4329bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndShowAlert();
4339bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            } else {
4349bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                stopVideoRecordingAndGetThumbnail();
4359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            }
4369bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } else {
4379bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            stopVideoRecording();
4389bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
439b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
440b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPausing = true;
441b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4429c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        unregisterReceiver(mReceiver);
443b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutSystemDefault();
444b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
4459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
4469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.storeData(ImageManager.getLastVideoThumbPath());
4479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
448095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin
449b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mStorageHint != null) {
450b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint.cancel();
451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mStorageHint = null;
452b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
453b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
454b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
455b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
456b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
457b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenTimeoutLong();
458b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
459b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch (keyCode) {
460b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_BACK:
461b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mMediaRecorderRecording) {
462de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
463b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
464d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                } else if (isAlertVisible()) {
4659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                    hideAlertAndStartPreview();
466b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
467b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
468b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
469b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_CAMERA:
470b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
471de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
472b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
473b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
474de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                break;
475b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_CENTER:
476b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (event.getRepeatCount() == 0) {
477de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
478de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    return true;
479b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
480b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
481b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            case KeyEvent.KEYCODE_MENU:
482b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                if (mMediaRecorderRecording) {
483de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project                    mShutterButton.performClick();
484b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    return true;
485b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
486b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                break;
487b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
488b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
489b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyDown(keyCode, event);
490b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
491b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
492b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
493b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
494b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        switch(keyCode) {
495b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        case KeyEvent.KEYCODE_CAMERA:
496b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mShutterButton.setPressed(false);
497b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return true;
498b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
499b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return super.onKeyUp(keyCode, event);
500b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
501b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
502b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
503314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber        if (mPausing) {
504314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // We're pausing, the screen is off and we already stopped
505314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // video recording. We don't want to start the camera again
506314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // in this case in order to conserve power.
507314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // The fact that surfaceChanged is called _after_ an onPause appears
508314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // to be legitimate since in that case the lockscreen always returns
509314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            // to portrait orientation possibly triggering the notification.
510314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber            return;
511314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber        }
512314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber
513b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        stopVideoRecording();
514b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        initializeVideo();
515b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
516b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
517b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceCreated(SurfaceHolder holder) {
518b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = holder;
519b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
520b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
521b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void surfaceDestroyed(SurfaceHolder holder) {
522b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mSurfaceHolder = null;
523b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
524b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
525b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    void gotoGallery() {
526b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.gotoCameraVideoGallery(this);
527b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
528b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
529b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
530b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onPrepareOptionsMenu(Menu menu) {
531b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onPrepareOptionsMenu(menu);
532b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
533b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        for (int i = 1; i <= MenuHelper.MENU_ITEM_MAX; i++) {
534b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (i != MenuHelper.GENERIC_ITEM) {
535b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                menu.setGroupVisible(i, false);
536b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
537b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
538b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
539b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        menu.setGroupVisible(MenuHelper.VIDEO_MODE_ITEM, true);
540b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
541b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
542b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
543b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    @Override
544b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public boolean onCreateOptionsMenu(Menu menu) {
545b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        super.onCreateOptionsMenu(menu);
546b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
5479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent) {
548b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // No options menu for attach mode.
549b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
550b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
551b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            addBaseMenuItems(menu);
552d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int menuFlags = MenuHelper.INCLUDE_ALL
553d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    & ~MenuHelper.INCLUDE_ROTATE_MENU
554095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin                    & ~MenuHelper.INCLUDE_DETAILS_MENU;
555b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            MenuHelper.addImageMenuItems(
556b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    menu,
557095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin                    menuFlags,
558b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    false,
559b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    VideoCamera.this,
56023c51b794e95c201290e36737f379c4bb8eefeaeRay Chen                    mHandler,
561b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // Handler for deletion
562b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    new Runnable() {
563b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run() {
564b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            // What do we do here?
565b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                            // mContentResolver.delete(uri, null, null);
566b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
567b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    },
568b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    new MenuHelper.MenuInvoker() {
569b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        public void run(final MenuHelper.MenuCallback cb) {
570b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        }
571b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    });
572b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
573d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.IMAGE_SAVING_ITEM,
574d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_SAVE_GALLERY_PHOTO, 0,
575d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    R.string.camera_gallery_photos_text)
576d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(
577d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    new MenuItem.OnMenuItemClickListener() {
578d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
579d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
580d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
581d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
582d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
583b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
584b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
585b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
588b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean isVideoCaptureIntent() {
589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String action = getIntent().getAction();
590b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action));
591b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
592b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
593b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void doReturnToCaller(boolean success) {
594b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent resultIntent = new Intent();
595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int resultCode;
596b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (success) {
597b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultCode = RESULT_OK;
598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultIntent.setData(mCurrentVideoUri);
599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
600b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            resultCode = RESULT_CANCELED;
601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
602b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setResult(resultCode, resultIntent);
603b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        finish();
604b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
605b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
606b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
607b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * Returns
608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * @return number of bytes available, or an ERROR code.
609b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
610b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private static long getAvailableStorage() {
611b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
612b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (!ImageManager.hasStorage()) {
613b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return NO_STORAGE_ERROR;
614b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
615d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                String storageDirectory = Environment
616d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        .getExternalStorageDirectory().toString();
617b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                StatFs stat = new StatFs(storageDirectory);
618d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                return ((long) stat.getAvailableBlocks()
619d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        * (long) stat.getBlockSize());
620b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
62123c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        } catch (RuntimeException ex) {
622b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // if we can't stat the filesystem then we don't know how many
623b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // free bytes exist.  It might be zero but just leave it
624b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // blank since we really don't know.
625b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return CANNOT_STAT_ERROR;
626b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
628b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
629b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void cleanupEmptyFile() {
630b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraVideoFilename != null) {
631b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            File f = new File(mCameraVideoFilename);
632b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (f.length() == 0 && f.delete()) {
633b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project              Log.v(TAG, "Empty video file deleted: " + mCameraVideoFilename);
634b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project              mCameraVideoFilename = null;
635b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
636b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
637b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
638b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6399bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    // initializeVideo() starts preview and prepare media recorder.
640b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // Returns false if initializeVideo fails
641b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean initializeVideo() {
642b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "initializeVideo");
6439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
6449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // We will call initializeVideo() again when the alert is hidden.
64523c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        if (isAlertVisible()) {
64623c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            return false;
64723c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        }
6489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
649b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Intent intent = getIntent();
650b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Bundle myExtras = intent.getExtras();
651b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent && myExtras != null) {
653b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
654b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (saveUri != null) {
655b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
656b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCameraVideoFileDescriptor = mContentResolver.
657b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                        openFileDescriptor(saveUri, "rw").getFileDescriptor();
658b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCurrentVideoUri = saveUri;
659d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                } catch (java.io.FileNotFoundException ex) {
660b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    // invalid uri
661b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.e(TAG, ex.toString());
662b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
663b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
665b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        releaseMediaRecorder();
666b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
667b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mSurfaceHolder == null) {
668b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "SurfaceHolder is null");
669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
671b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
672b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder = new MediaRecorder();
673b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
674d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
675b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
676b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
677b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
6788d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        mMediaRecorder.setMaxDuration(MAX_RECORDING_DURATION_MS);
6798d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
6809a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (mStorageStatus != STORAGE_STATUS_OK) {
681b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.setOutputFile("/dev/null");
682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
683d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // We try Uri in intent first. If it doesn't work, use our own
684d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // instead.
685b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mCameraVideoFileDescriptor != null) {
686b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOutputFile(mCameraVideoFileDescriptor);
687b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } else {
688b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                createVideoPath();
689b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOutputFile(mCameraVideoFilename);
690b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
691b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
692b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
693d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        boolean videoQualityHigh = getBooleanPreference(
694d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                CameraSettings.KEY_VIDEO_QUALITY,
695b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                CameraSettings.DEFAULT_VIDEO_QUALITY_VALUE);
696b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
697b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) {
698d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int extraVideoQuality = intent.getIntExtra(
699d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MediaStore.EXTRA_VIDEO_QUALITY, 0);
700b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            videoQualityHigh = (extraVideoQuality > 0);
701b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
702b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
703b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // Use the same frame rate for both, since internally
704b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // if the frame rate is too large, it can cause camera to become
705b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // unstable. We need to fix the MediaRecorder to disable the support
706b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        // of setting frame rate for now.
707b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoFrameRate(20);
708b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (videoQualityHigh) {
709d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mMediaRecorder.setVideoSize(352, 288);
710b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } else {
711d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mMediaRecorder.setVideoSize(176, 144);
712b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
713b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
714d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
715b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
716de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
717de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        long remaining = getAvailableStorage();
718de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        // remaining >= LOW_STORAGE_THRESHOLD at this point, reserve a quarter
719d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // of that to make it more likely that recording can complete
720d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // successfully.
721de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        try {
722d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mMediaRecorder.setMaxFileSize(remaining -
723d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    LOW_STORAGE_THRESHOLD / 4);
724de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        } catch (RuntimeException exception) {
725de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // We are going to ignore failure of setMaxFileSize here, as
726de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // a) The composer selected may simply not support it, or
727de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            // b) The underlying media framework may not handle 64-bit range
728de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            //    on the size restriction.
729de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        }
730de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
731b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
732b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.prepare();
733b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (IOException exception) {
734b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.e(TAG, "prepare failed for " + mCameraVideoFilename);
735b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            releaseMediaRecorder();
736b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // TODO: add more exception handling logic here
737b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            return false;
738b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
739b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mMediaRecorderRecording = false;
7409bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
7419bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent && !mThumbController.isUriValid()) {
7429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            updateLastVideo();
7439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
7449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
7459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
7469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.updateDisplayIfNeeded();
7479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
7489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
749b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return true;
750b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
751b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
752b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void releaseMediaRecorder() {
753b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Releasing media recorder.");
754b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mMediaRecorder != null) {
755b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            cleanupEmptyFile();
756b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.reset();
757b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder.release();
758b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorder = null;
759b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
760b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
761b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
762b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private int getIntPreference(String key, int defaultValue) {
763b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String s = mPreferences.getString(key, "");
764b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int result = defaultValue;
765b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        try {
766b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            result = Integer.parseInt(s);
767b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        } catch (NumberFormatException e) {
768b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Ignore, result is already the default value.
769b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
770b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return result;
771b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
772b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
773b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private boolean getBooleanPreference(String key, boolean defaultValue) {
774b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return getIntPreference(key, defaultValue ? 1 : 0) != 0;
775b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
776b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
777b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void createVideoPath() {
778b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        long dateTaken = System.currentTimeMillis();
779b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String title = createName(dateTaken);
780b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String displayName = title + ".3gp"; // Used when emailing.
781b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME;
782b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        File cameraDir = new File(cameraDirPath);
783b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        cameraDir.mkdirs();
784b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        SimpleDateFormat dateFormat = new SimpleDateFormat(
785b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                getString(R.string.video_file_name_format));
786b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Date date = new Date(dateTaken);
787b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String filepart = dateFormat.format(date);
788b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        String filename = cameraDirPath + "/" + filepart + ".3gp";
789b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        ContentValues values = new ContentValues(7);
790b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.TITLE, title);
791b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DISPLAY_NAME, displayName);
792b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DATE_TAKEN, dateTaken);
793b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.MIME_TYPE, "video/3gpp");
794b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        values.put(Video.Media.DATA, filename);
795b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFilename = filename;
796b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Current camera video filename: " + mCameraVideoFilename);
797b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCurrentVideoValues = values;
798b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
799b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
800b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void registerVideo() {
801b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCameraVideoFileDescriptor == null) {
802b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Uri videoTable = Uri.parse("content://media/external/video/media");
803b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoUri = mContentResolver.insert(videoTable,
804b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mCurrentVideoValues);
805b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "Current video URI: " + mCurrentVideoUri);
806b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
807b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCurrentVideoValues = null;
808b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
809b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
810b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void deleteCurrentVideo() {
811b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCurrentVideoFilename != null) {
812b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            deleteVideoFile(mCurrentVideoFilename);
813b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoFilename = null;
814b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
815b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mCurrentVideoUri != null) {
816b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mContentResolver.delete(mCurrentVideoUri, null, null);
817b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mCurrentVideoUri = null;
818b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
819de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        updateAndShowStorageHint(true);
820b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
821b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
822b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void deleteVideoFile(String fileName) {
823b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "Deleting video " + fileName);
824b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        File f = new File(fileName);
825d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (!f.delete()) {
826b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Log.v(TAG, "Could not delete " + fileName);
827b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
828b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
829b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
830b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void addBaseMenuItems(Menu menu) {
831b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        MenuHelper.addSwitchModeMenuItem(menu, this, false);
832b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
833d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.IMAGE_MODE_ITEM,
834d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_GALLERY_PHOTOS, 0, R.string.camera_gallery_photos_text)
835d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
836d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
837d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
838d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
839d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
840d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
841b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
842b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
843b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
844b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        {
845d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            MenuItem gallery = menu.add(MenuHelper.VIDEO_MODE_ITEM,
846d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    MENU_GALLERY_VIDEOS, 0, R.string.camera_gallery_photos_text)
847d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
848d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        public boolean onMenuItemClick(MenuItem item) {
849d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            gotoGallery();
850d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            return true;
851d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        }
852d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    });
853b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            gallery.setIcon(android.R.drawable.ic_menu_gallery);
854b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mGalleryItems.add(gallery);
855b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
856b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
857d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        MenuItem item = menu.add(MenuHelper.GENERIC_ITEM, MENU_SETTINGS, 0,
858d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                R.string.settings)
859d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                .setOnMenuItemClickListener(new OnMenuItemClickListener() {
860d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    public boolean onMenuItemClick(MenuItem item) {
861d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        Intent intent = new Intent();
862d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        intent.setClass(VideoCamera.this, CameraSettings.class);
863d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        startActivity(intent);
864d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        return true;
865d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    }
866d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                });
867b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        item.setIcon(android.R.drawable.ic_menu_preferences);
868b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
869b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
870b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    // from MediaRecorder.OnErrorListener
871b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void onError(MediaRecorder mr, int what, int extra) {
872b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) {
873b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // We may have run out of space on the sdcard.
874b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            stopVideoRecording();
8759a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            updateAndShowStorageHint(true);
876b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
877b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
878b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
8798d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    // from MediaRecorder.OnInfoListener
8808d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    public void onInfo(MediaRecorder mr, int what, int extra) {
8818d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
882de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            mShutterButton.performClick();
883d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        } else if (what
884d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
885de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            mShutterButton.performClick();
886de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            updateAndShowStorageHint(true);
8878d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        }
8888d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project    }
8898d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
8909c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    /*
8919c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     * Make sure we're not recording music playing in the background, ask
8929c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     * the MediaPlaybackService to pause playback.
8939c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project     */
8949c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    private void pauseAudioPlayback() {
8959c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // Shamelessly copied from MediaPlaybackService.java, which
8969c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        // should be public, but isn't.
8979c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        Intent i = new Intent("com.android.music.musicservicecommand");
8989c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        i.putExtra("command", "pause");
8999c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
9009c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project        sendBroadcast(i);
9019c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project    }
9029c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
903b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void startVideoRecording() {
904b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "startVideoRecording");
905b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (!mMediaRecorderRecording) {
906b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
9079a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            if (mStorageStatus != STORAGE_STATUS_OK) {
908b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.v(TAG, "Storage issue, ignore the start request");
909b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
910b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
911b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
912b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // Check mMediaRecorder to see whether it is initialized or not.
913d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            if (mMediaRecorder == null && initializeVideo() == false) {
914b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Initialize video (MediaRecorder) failed.");
915b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
916b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
917b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
9189c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project            pauseAudioPlayback();
9199c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project
920b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            try {
921b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.setOnErrorListener(this);
9228d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                mMediaRecorder.setOnInfoListener(this);
923b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorder.start();   // Recording is now started
924b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            } catch (RuntimeException e) {
925b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                Log.e(TAG, "Could not start media recorder. ", e);
926b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                return;
927b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
928b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mMediaRecorderRecording = true;
929b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingStartTime = SystemClock.uptimeMillis();
930b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateRecordingIndicator(true);
931b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setText("");
932b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setVisibility(View.VISIBLE);
933b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mHandler.sendEmptyMessage(UPDATE_RECORD_TIME);
934b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setScreenTimeoutInfinite();
935de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project            hideLastPictureButton();
936b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
937b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
938b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
939b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void updateRecordingIndicator(boolean showRecording) {
940d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        int drawableId = showRecording
941d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                ? R.drawable.ic_camera_bar_indicator_record
942d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                : R.drawable.ic_camera_indicator_video;
943b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Drawable drawable = getResources().getDrawable(drawableId);
944b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mShutterButton.setImageDrawable(drawable);
945b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
946b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
9479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void stopVideoRecordingAndGetThumbnail() {
9489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        stopVideoRecording();
9499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        acquireVideoThumb();
950b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
951b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
952de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    private void stopVideoRecordingAndShowAlert() {
953de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        stopVideoRecording();
9549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        showAlert();
955de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
956de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
9579bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void showAlert() {
958b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] pickIds = {R.id.attach, R.id.cancel};
959b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] normalIds = {R.id.gallery, R.id.share, R.id.discard};
960b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] alwaysOnIds = {R.id.play};
961b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] hideIds = pickIds;
962b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        int[] connectIds = normalIds;
9639bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (mIsVideoCaptureIntent) {
964b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            hideIds = normalIds;
965b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            connectIds = pickIds;
966b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
967d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        for (int id : hideIds) {
968b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mPostPictureAlert.findViewById(id).setVisibility(View.GONE);
969b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
9708d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        ActionMenuButton shareButton =
9718d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                (ActionMenuButton) mPostPictureAlert.findViewById(R.id.share);
9728d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project        shareButton.setRestricted(
9738d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                mCurrentVideoFileLength > SHARE_FILE_LENGTH_LIMIT);
974b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        connectAndFadeIn(connectIds);
975b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        connectAndFadeIn(alwaysOnIds);
976de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        hideLastPictureButton();
977b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mPostPictureAlert.setVisibility(View.VISIBLE);
9789bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
9799bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // There are two cases we are here:
9809bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // (1) We are in a capture video intent, and we are reviewing the video
981095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin        //     we just taken.
9829bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // (2) The thumbnail button is clicked: we review the video associated
9839bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        //     with the thumbnail.
9849bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // For the second case, we copy the associated URI and filename to
9859bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // mCurrentVideoUri and mCurrentVideoFilename, so the video frame shown
9869bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        // and the target for actions (play, delete, ...) will be correct.
9879bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
9889bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
9899bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mCurrentVideoUri = mThumbController.getUri();
9909bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mCurrentVideoFilename = getDataPath(mCurrentVideoUri);
9919bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
9929bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
9939bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        String path = mCurrentVideoFilename;
9949bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (path != null) {
995101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            Bitmap videoFrame = Util.createVideoThumbnail(path);
9969bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mVideoFrame.setImageBitmap(videoFrame);
9979bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mVideoFrame.setVisibility(View.VISIBLE);
9989bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
999b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1000b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10019bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlert() {
1002de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mVideoFrame.setVisibility(View.INVISIBLE);
1003de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        mPostPictureAlert.setVisibility(View.INVISIBLE);
1004de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        showLastPictureButton();
1005de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1006de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
1007b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void connectAndFadeIn(int[] connectIds) {
1008d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        for (int id : connectIds) {
1009b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            View view = mPostPictureAlert.findViewById(id);
1010b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            view.setOnClickListener(this);
1011b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            Animation animation = new AlphaAnimation(0F, 1F);
1012b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            animation.setDuration(500);
10139bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            view.startAnimation(animation);
1014b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1015b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1016b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10179bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private boolean isAlertVisible() {
1018b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return mPostPictureAlert.getVisibility() == View.VISIBLE;
1019b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1020b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1021b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void stopVideoRecording() {
1022b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Log.v(TAG, "stopVideoRecording");
1023b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        boolean needToRegisterRecording = false;
1024b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mMediaRecorderRecording || mMediaRecorder != null) {
1025b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mMediaRecorderRecording && mMediaRecorder != null) {
1026b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                try {
1027b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mMediaRecorder.setOnErrorListener(null);
10288d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    mMediaRecorder.setOnInfoListener(null);
1029b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    mMediaRecorder.stop();
1030b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                } catch (RuntimeException e) {
1031b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                    Log.e(TAG, "stop fail: " + e.getMessage());
1032b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                }
10338d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project
1034b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mCurrentVideoFilename = mCameraVideoFilename;
10358d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                try {
1036d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    mCurrentVideoFileLength =
1037d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                            new File(mCurrentVideoFilename).length();
10388d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                } catch (RuntimeException e) {
10398d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    Log.e(TAG, "get file length fail: " + e.getMessage());
10408d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                    mCurrentVideoFileLength = 0;
10418d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project                }
1042d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                Log.v(TAG, "Setting current video filename: "
1043d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                        + mCurrentVideoFilename);
1044b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                needToRegisterRecording = true;
1045b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mMediaRecorderRecording = false;
1046b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
1047b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            releaseMediaRecorder();
1048b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            updateRecordingIndicator(false);
1049b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mRecordingTimeView.setVisibility(View.GONE);
1050b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            setScreenTimeoutLong();
1051b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
10529a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        if (needToRegisterRecording && mStorageStatus == STORAGE_STATUS_OK) {
10539a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project            registerVideo();
10549a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project        }
1055b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1056b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFilename = null;
1057b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mCameraVideoFileDescriptor = null;
1058b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1059b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1060b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutSystemDefault() {
1061b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1062b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        clearScreenOnFlag();
1063b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1064b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1065b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutLong() {
1066b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1067b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenOnFlag();
1068b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
1069b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1070b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1071b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenTimeoutInfinite() {
1072b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
1073b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        setScreenOnFlag();
1074b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1075b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1076b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void clearScreenOnFlag() {
1077b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window w = getWindow();
1078d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1079d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if ((w.getAttributes().flags & flag) != 0) {
1080d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            w.clearFlags(flag);
1081b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1082b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1083b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
1084b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private void setScreenOnFlag() {
1085b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        Window w = getWindow();
1086d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
1087d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if ((w.getAttributes().flags & flag) == 0) {
1088d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            w.addFlags(flag);
1089b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1090b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1091b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10929bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlertAndStartPreview() {
10939bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlert();
10949bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        initializeVideo();
1095b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1096b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
10979bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideAlertAndStartVideoRecording() {
10989bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        hideAlert();
10999bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        startVideoRecording();
1100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11029bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void acquireVideoThumb() {
1103101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        Bitmap videoFrame = Util.createVideoThumbnail(mCurrentVideoFilename);
11049bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        mThumbController.setData(mCurrentVideoUri, videoFrame);
1105de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1106de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
11079bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void showLastPictureButton() {
11089bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
11099bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setVisibility(View.VISIBLE);
1110de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project        }
11119bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    }
1112de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
11139bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void hideLastPictureButton() {
11149bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (!mIsVideoCaptureIntent) {
11159bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mLastPictureButton.setVisibility(View.INVISIBLE);
11169bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
1117de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1118de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
11199bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static ImageManager.DataLocation dataLocation() {
11209bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        return ImageManager.DataLocation.EXTERNAL;
1121de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project    }
1122de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project
11239bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private void updateLastVideo() {
1124101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        IImageList list = ImageManager.instance().allImages(
11259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            this,
11269bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mContentResolver,
11279bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            dataLocation(),
11289bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.INCLUDE_VIDEOS,
11299bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.SORT_ASCENDING,
11309bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            ImageManager.CAMERA_IMAGE_BUCKET_ID);
11319bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        int count = list.getCount();
11329bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        if (count > 0) {
1133d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            IImage image = list.getImageAt(count - 1);
11349bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            Uri uri = image.fullSizeImageUri();
11359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(uri, image.miniThumbBitmap());
11369bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } else {
11379bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            mThumbController.setData(null, null);
11389bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        }
11399bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        list.deactivate();
1140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
11429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private static final String[] DATA_PATH_PROJECTION = new String[] {
11439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        "_data"
11449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    };
11459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang
11469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang    private String getDataPath(Uri uri) {
11479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        Cursor c = null;
11489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        try {
1149d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            c = mContentResolver.query(uri, DATA_PATH_PROJECTION, null, null,
1150d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    null);
11519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            if (c != null && c.moveToFirst()) {
11529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                return c.getString(0);
11539bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            } else {
11549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang                return null;
11559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang            }
11569bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang        } finally {
115723c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            if (c != null) {
115823c51b794e95c201290e36737f379c4bb8eefeaeRay Chen                c.close();
115923c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            }
1160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
1161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
1162d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1163d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    private void updateRecordingTime() {
116423c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        if (!mMediaRecorderRecording) {
116523c51b794e95c201290e36737f379c4bb8eefeaeRay Chen            return;
116623c51b794e95c201290e36737f379c4bb8eefeaeRay Chen        }
1167d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long now = SystemClock.uptimeMillis();
1168d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long delta = now - mRecordingStartTime;
1169d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1170d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // Starting a minute before reaching the max duration
1171d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // limit, we'll countdown the remaining time instead.
1172d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        boolean countdownRemainingTime =
1173d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            (delta >= MAX_RECORDING_DURATION_MS - 60000);
1174d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1175d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (countdownRemainingTime) {
1176d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            delta = Math.max(0, MAX_RECORDING_DURATION_MS - delta);
1177d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1178d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1179d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long seconds = (delta + 500) / 1000;  // round to nearest
1180d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long minutes = seconds / 60;
1181d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long hours = minutes / 60;
1182d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long remainderMinutes = minutes - (hours * 60);
1183d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        long remainderSeconds = seconds - (minutes * 60);
1184d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1185d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String secondsString = Long.toString(remainderSeconds);
1186d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (secondsString.length() < 2) {
1187d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            secondsString = "0" + secondsString;
1188d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1189d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String minutesString = Long.toString(remainderMinutes);
1190d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (minutesString.length() < 2) {
1191d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            minutesString = "0" + minutesString;
1192d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1193d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        String text = minutesString + ":" + secondsString;
1194d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (hours > 0) {
1195d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            String hoursString = Long.toString(hours);
1196d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            if (hoursString.length() < 2) {
1197d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                hoursString = "0" + hoursString;
1198d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            }
1199d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            text = hoursString + ":" + text;
1200d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1201d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mRecordingTimeView.setText(text);
1202d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1203d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        if (mRecordingTimeCountsDown != countdownRemainingTime) {
1204d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // Avoid setting the color on every update, do it only
1205d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            // when it needs changing.
1206d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1207d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mRecordingTimeCountsDown = countdownRemainingTime;
1208d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1209d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            int color = getResources().getColor(
1210d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    countdownRemainingTime
1211d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    ? R.color.recording_time_remaining_text
1212d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang                    : R.color.recording_time_elapsed_text);
1213d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1214d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang            mRecordingTimeView.setTextColor(color);
1215d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        }
1216d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang
1217d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // Work around a limitation of the T-Mobile G1: The T-Mobile
1218d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // hardware blitter can't pixel-accurately scale and clip at the
1219d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // same time, and the SurfaceFlinger doesn't attempt to work around
1220d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // this limitation. In order to avoid visual corruption we must
1221d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // manually refresh the entire surface view when changing any
1222d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        // overlapping view's contents.
1223d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mVideoPreview.invalidate();
1224d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang        mHandler.sendEmptyMessageDelayed(UPDATE_RECORD_TIME, 1000);
1225d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang    }
1226b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project}
1227