1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera.functional; 18 19 import com.android.camera.VideoCamera; 20 import com.android.camera.R; 21 22 import android.app.Activity; 23 import android.app.Instrumentation; 24 import android.content.ContentResolver; 25 import android.content.Intent; 26 import android.database.Cursor; 27 import android.media.MediaMetadataRetriever; 28 import android.net.Uri; 29 import android.os.Environment; 30 import android.os.Process; 31 import android.provider.MediaStore; 32 import android.provider.MediaStore.Video.VideoColumns; 33 import android.test.ActivityInstrumentationTestCase2; 34 import android.test.suitebuilder.annotation.LargeTest; 35 import android.test.UiThreadTest; 36 import android.util.Log; 37 import android.view.KeyEvent; 38 import android.view.View; 39 40 import java.io.BufferedInputStream; 41 import java.io.File; 42 import java.io.FileInputStream; 43 import java.net.URI; 44 45 public class VideoCaptureIntentTest extends ActivityInstrumentationTestCase2 <VideoCamera> { 46 private static final String TAG = "VideoCaptureIntentTest"; 47 private Intent mIntent; 48 private Uri mVideoUri; 49 private File mFile, mFile2; 50 51 public VideoCaptureIntentTest() { 52 super(VideoCamera.class); 53 } 54 55 @Override 56 protected void setUp() throws Exception { 57 super.setUp(); 58 mIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); 59 } 60 61 @Override 62 protected void tearDown() throws Exception { 63 if (mVideoUri != null) { 64 ContentResolver resolver = getActivity().getContentResolver(); 65 Uri query = mVideoUri.buildUpon().build(); 66 String[] projection = new String[] {VideoColumns.DATA}; 67 68 Cursor cursor = null; 69 try { 70 cursor = resolver.query(query, projection, null, null, null); 71 if (cursor != null && cursor.moveToFirst()) { 72 new File(cursor.getString(0)).delete(); 73 } 74 } finally { 75 if (cursor != null) cursor.close(); 76 } 77 78 resolver.delete(mVideoUri, null, null); 79 } 80 if (mFile != null) mFile.delete(); 81 if (mFile2 != null) mFile2.delete(); 82 super.tearDown(); 83 } 84 85 @LargeTest 86 public void testNoExtraOutput() throws Exception { 87 setActivityIntent(mIntent); 88 getActivity(); 89 90 recordVideo(); 91 pressDone(); 92 93 Intent resultData = getActivity().getResultData(); 94 mVideoUri = resultData.getData(); 95 assertNotNull(mVideoUri); 96 verify(getActivity(), mVideoUri); 97 } 98 99 @LargeTest 100 public void testExtraOutput() throws Exception { 101 mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); 102 103 Uri uri = Uri.fromFile(mFile); 104 mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); 105 setActivityIntent(mIntent); 106 getActivity(); 107 108 recordVideo(); 109 pressDone(); 110 111 verify(getActivity(), uri); 112 } 113 114 @LargeTest 115 public void testRetake() throws Exception { 116 setActivityIntent(mIntent); 117 getActivity(); 118 119 recordVideo(); 120 pressRetake(); 121 recordVideo(); 122 pressDone(); 123 124 Intent resultData = getActivity().getResultData(); 125 mVideoUri = resultData.getData(); 126 assertNotNull(mVideoUri); 127 verify(getActivity(), mVideoUri); 128 } 129 130 @LargeTest 131 public void testCancel() throws Exception { 132 setActivityIntent(mIntent); 133 getActivity(); 134 135 pressCancel(); 136 137 assertTrue(getActivity().isFinishing()); 138 assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); 139 } 140 141 @LargeTest 142 public void testRecordCancel() throws Exception { 143 setActivityIntent(mIntent); 144 getActivity(); 145 146 recordVideo(); 147 pressCancel(); 148 149 assertTrue(getActivity().isFinishing()); 150 assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); 151 } 152 153 @LargeTest 154 public void testExtraSizeLimit() throws Exception { 155 mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); 156 final long sizeLimit = 500000; // bytes 157 158 Uri uri = Uri.fromFile(mFile); 159 mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); 160 mIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, sizeLimit); 161 mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); // use low quality to speed up 162 setActivityIntent(mIntent); 163 getActivity(); 164 165 recordVideo(5000); 166 pressDone(); 167 168 verify(getActivity(), uri); 169 long length = mFile.length(); 170 Log.v(TAG, "Video size is " + length + " bytes."); 171 assertTrue(length > 0); 172 assertTrue("Actual size=" + length, length <= sizeLimit); 173 } 174 175 @LargeTest 176 public void testExtraDurationLimit() throws Exception { 177 mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); 178 final int durationLimit = 2; // seconds 179 180 Uri uri = Uri.fromFile(mFile); 181 mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); 182 mIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, durationLimit); 183 setActivityIntent(mIntent); 184 getActivity(); 185 186 recordVideo(5000); 187 pressDone(); 188 189 int duration = verify(getActivity(), uri); 190 // The duraion should be close to to the limit. The last video duration 191 // also has duration, so the total duration may exceeds the limit a 192 // little bit. 193 Log.v(TAG, "Video length is " + duration + " ms."); 194 assertTrue(duration < (durationLimit + 1) * 1000); 195 } 196 197 @LargeTest 198 public void testExtraVideoQuality() throws Exception { 199 mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); 200 mFile2 = new File(Environment.getExternalStorageDirectory(), "video2.tmp"); 201 202 Uri uri = Uri.fromFile(mFile); 203 mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); 204 mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); // low quality 205 setActivityIntent(mIntent); 206 getActivity(); 207 208 recordVideo(); 209 pressDone(); 210 211 verify(getActivity(), uri); 212 setActivity(null); 213 214 uri = Uri.fromFile(mFile2); 215 mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); 216 mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // high quality 217 setActivityIntent(mIntent); 218 getActivity(); 219 220 recordVideo(); 221 pressDone(); 222 223 verify(getActivity(), uri); 224 assertTrue(mFile.length() <= mFile2.length()); 225 } 226 227 // Verify result code, result data, and the duration. 228 private int verify(VideoCamera activity, Uri uri) throws Exception { 229 assertTrue(activity.isFinishing()); 230 assertEquals(Activity.RESULT_OK, activity.getResultCode()); 231 232 // Verify the video file 233 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 234 retriever.setDataSource(activity, uri); 235 String duration = retriever.extractMetadata( 236 MediaMetadataRetriever.METADATA_KEY_DURATION); 237 assertNotNull(duration); 238 int durationValue = Integer.parseInt(duration); 239 Log.v(TAG, "Video duration is " + durationValue); 240 assertTrue(durationValue > 0); 241 return durationValue; 242 } 243 244 private void recordVideo(int ms) throws Exception { 245 getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_CAMERA); 246 Thread.sleep(ms); 247 getInstrumentation().runOnMainSync(new Runnable() { 248 public void run() { 249 // If recording is in progress, stop it. Run these atomically in 250 // UI thread. 251 if (getActivity().isRecording()) { 252 getActivity().findViewById(R.id.shutter_button).performClick(); 253 } 254 } 255 }); 256 } 257 258 private void recordVideo() throws Exception { 259 recordVideo(2000); 260 } 261 262 private void pressDone() { 263 getInstrumentation().runOnMainSync(new Runnable() { 264 public void run() { 265 getActivity().findViewById(R.id.btn_done).performClick(); 266 } 267 }); 268 } 269 270 private void pressRetake() { 271 getInstrumentation().runOnMainSync(new Runnable() { 272 public void run() { 273 getActivity().findViewById(R.id.btn_retake).performClick(); 274 } 275 }); 276 } 277 278 private void pressCancel() { 279 getInstrumentation().runOnMainSync(new Runnable() { 280 public void run() { 281 getActivity().findViewById(R.id.btn_cancel).performClick(); 282 } 283 }); 284 } 285 } 286