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 
VideoCaptureIntentTest()51     public VideoCaptureIntentTest() {
52         super(VideoCamera.class);
53     }
54 
55     @Override
setUp()56     protected void setUp() throws Exception {
57         super.setUp();
58         mIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
59     }
60 
61     @Override
tearDown()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
testNoExtraOutput()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
testExtraOutput()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
testRetake()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
testCancel()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
testRecordCancel()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
testExtraSizeLimit()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
testExtraDurationLimit()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