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.CameraActivity;
20 import com.android.camera2.R;
21 
22 import android.app.Activity;
23 import android.content.ContentResolver;
24 import android.content.Intent;
25 import android.database.Cursor;
26 import android.media.MediaMetadataRetriever;
27 import android.net.Uri;
28 import android.os.Environment;
29 import android.provider.MediaStore;
30 import android.provider.MediaStore.Video.VideoColumns;
31 import android.test.ActivityInstrumentationTestCase2;
32 import android.test.suitebuilder.annotation.LargeTest;
33 import android.util.Log;
34 import android.view.KeyEvent;
35 
36 import java.io.File;
37 
38 public class VideoCaptureIntentTest extends ActivityInstrumentationTestCase2 <CameraActivity> {
39     private static final String TAG = "VideoCaptureIntentTest";
40     private Intent mIntent;
41     private Uri mVideoUri;
42     private File mFile, mFile2;
43 
VideoCaptureIntentTest()44     public VideoCaptureIntentTest() {
45         super(CameraActivity.class);
46     }
47 
48     @Override
setUp()49     protected void setUp() throws Exception {
50         super.setUp();
51         mIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
52     }
53 
54     @Override
tearDown()55     protected void tearDown() throws Exception {
56         if (mVideoUri != null) {
57             ContentResolver resolver = getActivity().getContentResolver();
58             Uri query = mVideoUri.buildUpon().build();
59             String[] projection = new String[] {VideoColumns.DATA};
60 
61             Cursor cursor = null;
62             try {
63                 cursor = resolver.query(query, projection, null, null, null);
64                 if (cursor != null && cursor.moveToFirst()) {
65                     new File(cursor.getString(0)).delete();
66                 }
67             } finally {
68                 if (cursor != null) cursor.close();
69             }
70 
71             resolver.delete(mVideoUri, null, null);
72         }
73         if (mFile != null) mFile.delete();
74         if (mFile2 != null) mFile2.delete();
75         super.tearDown();
76     }
77 
78     @LargeTest
testNoExtraOutput()79     public void testNoExtraOutput() throws Exception {
80         setActivityIntent(mIntent);
81         getActivity();
82 
83         recordVideo();
84         pressDone();
85 
86         Intent resultData = getActivity().getResultData();
87         mVideoUri = resultData.getData();
88         assertNotNull(mVideoUri);
89         verify(getActivity(), mVideoUri);
90     }
91 
92     @LargeTest
testExtraOutput()93     public void testExtraOutput() throws Exception {
94         mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp");
95 
96         Uri uri = Uri.fromFile(mFile);
97         mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
98         setActivityIntent(mIntent);
99         getActivity();
100 
101         recordVideo();
102         pressDone();
103 
104         verify(getActivity(), uri);
105     }
106 
107     @LargeTest
testCancel()108     public void testCancel() throws Exception {
109         setActivityIntent(mIntent);
110         getActivity();
111 
112         pressCancel();
113 
114         assertTrue(getActivity().isFinishing());
115         assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode());
116     }
117 
118     @LargeTest
testRecordCancel()119     public void testRecordCancel() throws Exception {
120         setActivityIntent(mIntent);
121         getActivity();
122 
123         recordVideo();
124         pressCancel();
125 
126         assertTrue(getActivity().isFinishing());
127         assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode());
128     }
129 
130     @LargeTest
testExtraSizeLimit()131     public void testExtraSizeLimit() throws Exception {
132         mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp");
133         final long sizeLimit = 500000;  // bytes
134 
135         Uri uri = Uri.fromFile(mFile);
136         mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
137         mIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, sizeLimit);
138         mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);  // use low quality to speed up
139         setActivityIntent(mIntent);
140         getActivity();
141 
142         recordVideo(5000);
143         pressDone();
144 
145         verify(getActivity(), uri);
146         long length = mFile.length();
147         Log.v(TAG, "Video size is " + length + " bytes.");
148         assertTrue(length > 0);
149         assertTrue("Actual size=" + length, length <= sizeLimit);
150     }
151 
152     @LargeTest
testExtraDurationLimit()153     public void testExtraDurationLimit() throws Exception {
154         mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp");
155         final int durationLimit = 2;  // seconds
156 
157         Uri uri = Uri.fromFile(mFile);
158         mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
159         mIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, durationLimit);
160         setActivityIntent(mIntent);
161         getActivity();
162 
163         recordVideo(5000);
164         pressDone();
165 
166         int duration = verify(getActivity(), uri);
167         // The duraion should be close to to the limit. The last video duration
168         // also has duration, so the total duration may exceeds the limit a
169         // little bit.
170         Log.v(TAG, "Video length is " + duration + " ms.");
171         assertTrue(duration  < (durationLimit + 1) * 1000);
172     }
173 
174     @LargeTest
175     public void testExtraVideoQuality() throws Exception {
176         mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp");
177         mFile2 = new File(Environment.getExternalStorageDirectory(), "video2.tmp");
178 
179         Uri uri = Uri.fromFile(mFile);
180         mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
181         mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);  // low quality
182         setActivityIntent(mIntent);
183         getActivity();
184 
185         recordVideo();
186         pressDone();
187 
188         verify(getActivity(), uri);
189         setActivity(null);
190 
191         uri = Uri.fromFile(mFile2);
192         mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
193         mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);  // high quality
194         setActivityIntent(mIntent);
195         getActivity();
196 
197         recordVideo();
198         pressDone();
199 
200         verify(getActivity(), uri);
201         assertTrue(mFile.length() <= mFile2.length());
202     }
203 
204     // Verify result code, result data, and the duration.
205     private int verify(CameraActivity activity, Uri uri) throws Exception {
206         assertTrue(activity.isFinishing());
207         assertEquals(Activity.RESULT_OK, activity.getResultCode());
208 
209         // Verify the video file
210         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
211         retriever.setDataSource(activity, uri);
212         String duration = retriever.extractMetadata(
213                 MediaMetadataRetriever.METADATA_KEY_DURATION);
214         assertNotNull(duration);
215         int durationValue = Integer.parseInt(duration);
216         Log.v(TAG, "Video duration is " + durationValue);
217         assertTrue(durationValue > 0);
218         return durationValue;
219     }
220 
221     private void recordVideo(int ms) throws Exception {
222         getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_CAMERA);
223         Thread.sleep(ms);
224         getInstrumentation().runOnMainSync(new Runnable() {
225             @Override
226             public void run() {
227                 // If recording is in progress, stop it. Run these atomically in
228                 // UI thread.
229                 CameraActivity activity = getActivity();
230                 if (activity.isRecording()) {
231                     activity.findViewById(R.id.shutter_button).performClick();
232                 }
233             }
234         });
235     }
236 
237     private void recordVideo() throws Exception {
238         recordVideo(2000);
239     }
240 
241     private void pressDone() {
242         getInstrumentation().runOnMainSync(new Runnable() {
243             @Override
244             public void run() {
245                 getActivity().findViewById(R.id.btn_done).performClick();
246             }
247         });
248     }
249 
250     private void pressCancel() {
251         getInstrumentation().runOnMainSync(new Runnable() {
252             @Override
253             public void run() {
254                 getActivity().findViewById(R.id.btn_cancel).performClick();
255             }
256         });
257     }
258 }
259