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
17package com.android.camera.functional;
18
19import com.android.camera.CameraActivity;
20import com.android.camera2.R;
21
22import android.app.Activity;
23import android.content.ContentResolver;
24import android.content.Intent;
25import android.database.Cursor;
26import android.media.MediaMetadataRetriever;
27import android.net.Uri;
28import android.os.Environment;
29import android.provider.MediaStore;
30import android.provider.MediaStore.Video.VideoColumns;
31import android.test.ActivityInstrumentationTestCase2;
32import android.test.suitebuilder.annotation.LargeTest;
33import android.util.Log;
34import android.view.KeyEvent;
35
36import java.io.File;
37
38public 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
44    public VideoCaptureIntentTest() {
45        super(CameraActivity.class);
46    }
47
48    @Override
49    protected void setUp() throws Exception {
50        super.setUp();
51        mIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
52    }
53
54    @Override
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
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
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
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
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
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
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