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