From 1ac5817f362f6f8262bf00191e1e419996475380 Mon Sep 17 00:00:00 2001 From: Sascha Haeberling Date: Fri, 9 Aug 2013 14:43:07 -0700 Subject: Add camera-related tests back. Change-Id: I2213618fe3b2d4ba776c5f1f94aca330a785df1a --- tests/Android.mk | 18 ++ tests/AndroidManifest.xml | 48 ++++ tests/exiftool_parser/parser.py | 90 +++++++ tests/res/raw/android_lawn.mp4 | Bin 0 -> 1514621 bytes tests/res/raw/galaxy_nexus.jpg | Bin 0 -> 1018845 bytes tests/res/raw/jpeg_control.jpg | Bin 0 -> 116135 bytes tests/res/xml/galaxy_nexus.xml | 43 ++++ .../com/android/gallery3d/CameraTestRunner.java | 46 ++++ tests/src/com/android/gallery3d/StressTests.java | 47 ++++ .../android/gallery3d/functional/CameraTest.java | 81 +++++++ .../functional/ImageCaptureIntentTest.java | 148 ++++++++++++ .../functional/VideoCaptureIntentTest.java | 258 +++++++++++++++++++++ .../android/gallery3d/stress/CameraLatency.java | 148 ++++++++++++ .../android/gallery3d/stress/CameraStartUp.java | 155 +++++++++++++ .../gallery3d/stress/CameraStressTestRunner.java | 61 +++++ .../com/android/gallery3d/stress/ImageCapture.java | 119 ++++++++++ .../gallery3d/stress/ShotToShotLatency.java | 142 ++++++++++++ .../android/gallery3d/stress/SwitchPreview.java | 116 +++++++++ .../src/com/android/gallery3d/stress/TestUtil.java | 57 +++++ .../com/android/gallery3d/stress/VideoCapture.java | 112 +++++++++ .../android/gallery3d/unittest/CameraUnitTest.java | 107 +++++++++ 21 files changed, 1796 insertions(+) create mode 100644 tests/Android.mk create mode 100644 tests/AndroidManifest.xml create mode 100755 tests/exiftool_parser/parser.py create mode 100644 tests/res/raw/android_lawn.mp4 create mode 100755 tests/res/raw/galaxy_nexus.jpg create mode 100644 tests/res/raw/jpeg_control.jpg create mode 100644 tests/res/xml/galaxy_nexus.xml create mode 100755 tests/src/com/android/gallery3d/CameraTestRunner.java create mode 100755 tests/src/com/android/gallery3d/StressTests.java create mode 100644 tests/src/com/android/gallery3d/functional/CameraTest.java create mode 100644 tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java create mode 100644 tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java create mode 100755 tests/src/com/android/gallery3d/stress/CameraLatency.java create mode 100644 tests/src/com/android/gallery3d/stress/CameraStartUp.java create mode 100755 tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java create mode 100755 tests/src/com/android/gallery3d/stress/ImageCapture.java create mode 100644 tests/src/com/android/gallery3d/stress/ShotToShotLatency.java create mode 100755 tests/src/com/android/gallery3d/stress/SwitchPreview.java create mode 100644 tests/src/com/android/gallery3d/stress/TestUtil.java create mode 100755 tests/src/com/android/gallery3d/stress/VideoCapture.java create mode 100644 tests/src/com/android/gallery3d/unittest/CameraUnitTest.java diff --git a/tests/Android.mk b/tests/Android.mk new file mode 100644 index 000000000..9f33322f2 --- /dev/null +++ b/tests/Android.mk @@ -0,0 +1,18 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# We only want this apk build for tests. +LOCAL_MODULE_TAGS := tests + +LOCAL_SDK_VERSION := 16 + +LOCAL_STATIC_JAVA_LIBRARIES := littlemock dexmaker + +# Include all test java files. +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := Camera2Tests + +LOCAL_INSTRUMENTATION_FOR := Camera2 + +include $(BUILD_PACKAGE) diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml new file mode 100644 index 000000000..f44156ea4 --- /dev/null +++ b/tests/AndroidManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/exiftool_parser/parser.py b/tests/exiftool_parser/parser.py new file mode 100755 index 000000000..7df23f154 --- /dev/null +++ b/tests/exiftool_parser/parser.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# +# This parser parses the output from Phil Harvey's exiftool (version 9.02) +# and convert it to xml format. It reads exiftool's output from stdin and +# write the xml format to stdout. +# +# In order to get the raw infomation from exiftool, we need to enable the verbose +# flag (-v2) of exiftool. +# +# Usage: +# exiftool -v2 img.jpg | ./parser.py >> output.xml +# +# + +import os +import sys +import re + +text = sys.stdin.read() + +print """""" +print "" + +# find the following two groups of string: +# +# 1. tag: +# +# | | | x) name = value +# | | | - Tag 0x1234 +# +# 2. IFD indicator: +# +# | | | + [xxx directory with xx entries] +# +p = re.compile( + "(((?:\| )+)[0-9]*\)(?:(?:.*? = .*?)|(?:.*? \(SubDirectory\) -->))\n.*?- Tag 0x[0-9a-f]{4})" + "|" + + "(((?:\| )*)\+ \[.*? directory with [0-9]+ entries]$)" + , re.M) +tags = p.findall(text) + +layer = 0 +ifds = [] + +for s in tags: + # IFD indicator + if s[2]: + l = len(s[3]) + ifd = s[2][l + 3:].split()[0] + new_layer = l / 2 + 1 + if new_layer > layer: + ifds.append(ifd) + else: + for i in range(layer - new_layer): + ifds.pop() + ifds[-1] = ifd + layer = new_layer + else: + l = len(s[1]) + s = s[0] + new_layer = l / 2 + if new_layer < layer: + for i in range(layer - new_layer): + ifds.pop() + layer = new_layer + + # find the ID + _id = re.search("0x[0-9a-f]{4}", s) + _id = _id.group(0) + + # find the name + name = re.search("[0-9]*?\).*?(?:(?: = )|(?: \(SubDirectory\) -->))", s) + name = name.group(0).split()[1] + + # find the raw value in the parenthesis + value = re.search("\(SubDirectory\) -->", s) + if value: + value = "NO_VALUE" + else: + value = re.search("\(.*\)\n", s) + if (name != 'Model' and value): + value = value.group(0)[1:-2] + else: + value = re.search("=.*\n", s) + value = value.group(0)[2:-1] + if "[snip]" in value: + value = "NO_VALUE" + + print (' ' + value + "") +print "" diff --git a/tests/res/raw/android_lawn.mp4 b/tests/res/raw/android_lawn.mp4 new file mode 100644 index 000000000..bdeffbed7 Binary files /dev/null and b/tests/res/raw/android_lawn.mp4 differ diff --git a/tests/res/raw/galaxy_nexus.jpg b/tests/res/raw/galaxy_nexus.jpg new file mode 100755 index 000000000..de91df696 Binary files /dev/null and b/tests/res/raw/galaxy_nexus.jpg differ diff --git a/tests/res/raw/jpeg_control.jpg b/tests/res/raw/jpeg_control.jpg new file mode 100644 index 000000000..bb468a77c Binary files /dev/null and b/tests/res/raw/jpeg_control.jpg differ diff --git a/tests/res/xml/galaxy_nexus.xml b/tests/res/xml/galaxy_nexus.xml new file mode 100644 index 000000000..55dd524a4 --- /dev/null +++ b/tests/res/xml/galaxy_nexus.xml @@ -0,0 +1,43 @@ + + + 2560 + 1920 + google + Nexus S + 1 + MASTER + 2012:07:30 16:28:42 + 1 + NO_VALUE + 1/40 + 26/10 + 3 + 100 + 0220 + 2012:07:30 16:28:42 + 2012:07:30 16:28:42 + 50/10 + 30/10 + 30/10 + 0/0 + 30/10 + 2 + 0 + 343/100 + IICSAUser comments + 1 + 2560 + 1920 + 0 + 0 + 0 + 320 + 240 + 6 + 1 + 72/1 + 72/1 + 2 + 690 + 10447 + diff --git a/tests/src/com/android/gallery3d/CameraTestRunner.java b/tests/src/com/android/gallery3d/CameraTestRunner.java new file mode 100755 index 000000000..503233675 --- /dev/null +++ b/tests/src/com/android/gallery3d/CameraTestRunner.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d; + +import android.test.InstrumentationTestRunner; +import android.test.InstrumentationTestSuite; + +import com.android.gallery3d.functional.CameraTest; +import com.android.gallery3d.functional.ImageCaptureIntentTest; +import com.android.gallery3d.functional.VideoCaptureIntentTest; +import com.android.gallery3d.unittest.CameraUnitTest; + +import junit.framework.TestSuite; + + +public class CameraTestRunner extends InstrumentationTestRunner { + + @Override + public TestSuite getAllTests() { + TestSuite suite = new InstrumentationTestSuite(this); + suite.addTestSuite(CameraTest.class); + suite.addTestSuite(ImageCaptureIntentTest.class); + suite.addTestSuite(VideoCaptureIntentTest.class); + suite.addTestSuite(CameraUnitTest.class); + return suite; + } + + @Override + public ClassLoader getLoader() { + return CameraTestRunner.class.getClassLoader(); + } +} diff --git a/tests/src/com/android/gallery3d/StressTests.java b/tests/src/com/android/gallery3d/StressTests.java new file mode 100755 index 000000000..b991e9e8d --- /dev/null +++ b/tests/src/com/android/gallery3d/StressTests.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d; + +import com.android.gallery3d.stress.CameraLatency; +import com.android.gallery3d.stress.CameraStartUp; +import com.android.gallery3d.stress.ImageCapture; +import com.android.gallery3d.stress.SwitchPreview; + +import junit.framework.Test; +import junit.framework.TestSuite; + + +/** + * Instrumentation Test Runner for all Camera tests. + * + * Running all tests: + * + * adb shell am instrument \ + * -e class com.android.gallery3d.StressTests \ + * -w com.google.android.gallery3d.tests/com.android.gallery3d.stress.CameraStressTestRunner + */ + +public class StressTests extends TestSuite { + public static Test suite() { + TestSuite result = new TestSuite(); + result.addTestSuite(CameraLatency.class); + result.addTestSuite(CameraStartUp.class); + result.addTestSuite(ImageCapture.class); +// result.addTestSuite(SwitchPreview.class); + return result; + } +} diff --git a/tests/src/com/android/gallery3d/functional/CameraTest.java b/tests/src/com/android/gallery3d/functional/CameraTest.java new file mode 100644 index 000000000..c293c0d4a --- /dev/null +++ b/tests/src/com/android/gallery3d/functional/CameraTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.functional; + +import com.android.camera.CameraActivity; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Environment; +import android.os.Process; +import android.provider.MediaStore; +import android.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.LargeTest; + +import java.io.File; +import java.lang.ref.WeakReference; +import java.util.ArrayList; + +public class CameraTest extends InstrumentationTestCase { + @LargeTest + public void testVideoCaptureIntentFdLeak() throws Exception { + Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); + intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.parse("file://" + + Environment.getExternalStorageDirectory().toString() + + "test_fd_leak.3gp")); + getInstrumentation().startActivitySync(intent).finish(); + // Test if the fd is closed. + for (File f: new File("/proc/" + Process.myPid() + "/fd").listFiles()) { + assertEquals(-1, f.getCanonicalPath().indexOf("test_fd_leak.3gp")); + } + } + + @LargeTest + public void testActivityLeak() throws Exception { + checkActivityLeak(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); + checkActivityLeak(MediaStore.INTENT_ACTION_VIDEO_CAMERA); + } + + private void checkActivityLeak(String action) throws Exception { + final int TEST_COUNT = 5; + Intent intent = new Intent(action); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setClass(getInstrumentation().getTargetContext(), + CameraActivity.class); + ArrayList> refs = + new ArrayList>(); + for (int i = 0; i < TEST_COUNT; i++) { + Activity activity = getInstrumentation().startActivitySync(intent); + refs.add(new WeakReference(activity)); + activity.finish(); + getInstrumentation().waitForIdleSync(); + activity = null; + } + Runtime.getRuntime().gc(); + Runtime.getRuntime().runFinalization(); + Runtime.getRuntime().gc(); + int refCount = 0; + for (WeakReference c: refs) { + if (c.get() != null) refCount++; + } + // If applications are leaking activity, every reference is reachable. + assertTrue(refCount != TEST_COUNT); + } +} diff --git a/tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java b/tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java new file mode 100644 index 000000000..9ea912864 --- /dev/null +++ b/tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.functional; + +import com.android.camera.CameraActivity; +import com.android.camera2.R; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Environment; +import android.provider.MediaStore; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.LargeTest; +import android.view.KeyEvent; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; + +public class ImageCaptureIntentTest extends ActivityInstrumentationTestCase2 { + private Intent mIntent; + + public ImageCaptureIntentTest() { + super(CameraActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + } + + @LargeTest + public void testNoExtraOutput() throws Exception { + setActivityIntent(mIntent); + getActivity(); + + takePicture(); + pressDone(); + + assertTrue(getActivity().isFinishing()); + assertEquals(Activity.RESULT_OK, getActivity().getResultCode()); + Intent resultData = getActivity().getResultData(); + Bitmap bitmap = (Bitmap) resultData.getParcelableExtra("data"); + assertNotNull(bitmap); + assertTrue(bitmap.getWidth() > 0); + assertTrue(bitmap.getHeight() > 0); + } + + @LargeTest + public void testExtraOutput() throws Exception { + File file = new File(Environment.getExternalStorageDirectory(), + "test.jpg"); + BufferedInputStream stream = null; + byte[] jpegData; + + try { + mIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); + setActivityIntent(mIntent); + getActivity(); + + takePicture(); + pressDone(); + + assertTrue(getActivity().isFinishing()); + assertEquals(Activity.RESULT_OK, getActivity().getResultCode()); + + // Verify the jpeg file + int fileLength = (int) file.length(); + assertTrue(fileLength > 0); + jpegData = new byte[fileLength]; + stream = new BufferedInputStream(new FileInputStream(file)); + stream.read(jpegData); + } finally { + if (stream != null) stream.close(); + file.delete(); + } + + Bitmap b = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length); + assertTrue(b.getWidth() > 0); + assertTrue(b.getHeight() > 0); + } + + @LargeTest + public void testCancel() throws Exception { + setActivityIntent(mIntent); + getActivity(); + + pressCancel(); + + assertTrue(getActivity().isFinishing()); + assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); + } + + @LargeTest + public void testSnapshotCancel() throws Exception { + setActivityIntent(mIntent); + getActivity(); + + takePicture(); + pressCancel(); + + assertTrue(getActivity().isFinishing()); + assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); + } + + private void takePicture() throws Exception { + getInstrumentation().sendKeySync( + new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_FOCUS)); + getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_CAMERA); + Thread.sleep(4000); + } + + private void pressDone() { + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + getActivity().findViewById(R.id.btn_done).performClick(); + } + }); + } + + private void pressCancel() { + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + getActivity().findViewById(R.id.btn_cancel).performClick(); + } + }); + } +} diff --git a/tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java b/tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java new file mode 100644 index 000000000..349398949 --- /dev/null +++ b/tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.functional; + +import com.android.camera.CameraActivity; +import com.android.camera2.R; + +import android.app.Activity; +import android.content.ContentResolver; +import android.content.Intent; +import android.database.Cursor; +import android.media.MediaMetadataRetriever; +import android.net.Uri; +import android.os.Environment; +import android.provider.MediaStore; +import android.provider.MediaStore.Video.VideoColumns; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; +import android.view.KeyEvent; + +import java.io.File; + +public class VideoCaptureIntentTest extends ActivityInstrumentationTestCase2 { + private static final String TAG = "VideoCaptureIntentTest"; + private Intent mIntent; + private Uri mVideoUri; + private File mFile, mFile2; + + public VideoCaptureIntentTest() { + super(CameraActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); + } + + @Override + protected void tearDown() throws Exception { + if (mVideoUri != null) { + ContentResolver resolver = getActivity().getContentResolver(); + Uri query = mVideoUri.buildUpon().build(); + String[] projection = new String[] {VideoColumns.DATA}; + + Cursor cursor = null; + try { + cursor = resolver.query(query, projection, null, null, null); + if (cursor != null && cursor.moveToFirst()) { + new File(cursor.getString(0)).delete(); + } + } finally { + if (cursor != null) cursor.close(); + } + + resolver.delete(mVideoUri, null, null); + } + if (mFile != null) mFile.delete(); + if (mFile2 != null) mFile2.delete(); + super.tearDown(); + } + + @LargeTest + public void testNoExtraOutput() throws Exception { + setActivityIntent(mIntent); + getActivity(); + + recordVideo(); + pressDone(); + + Intent resultData = getActivity().getResultData(); + mVideoUri = resultData.getData(); + assertNotNull(mVideoUri); + verify(getActivity(), mVideoUri); + } + + @LargeTest + public void testExtraOutput() throws Exception { + mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); + + Uri uri = Uri.fromFile(mFile); + mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); + setActivityIntent(mIntent); + getActivity(); + + recordVideo(); + pressDone(); + + verify(getActivity(), uri); + } + + @LargeTest + public void testCancel() throws Exception { + setActivityIntent(mIntent); + getActivity(); + + pressCancel(); + + assertTrue(getActivity().isFinishing()); + assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); + } + + @LargeTest + public void testRecordCancel() throws Exception { + setActivityIntent(mIntent); + getActivity(); + + recordVideo(); + pressCancel(); + + assertTrue(getActivity().isFinishing()); + assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); + } + + @LargeTest + public void testExtraSizeLimit() throws Exception { + mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); + final long sizeLimit = 500000; // bytes + + Uri uri = Uri.fromFile(mFile); + mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); + mIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, sizeLimit); + mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); // use low quality to speed up + setActivityIntent(mIntent); + getActivity(); + + recordVideo(5000); + pressDone(); + + verify(getActivity(), uri); + long length = mFile.length(); + Log.v(TAG, "Video size is " + length + " bytes."); + assertTrue(length > 0); + assertTrue("Actual size=" + length, length <= sizeLimit); + } + + @LargeTest + public void testExtraDurationLimit() throws Exception { + mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); + final int durationLimit = 2; // seconds + + Uri uri = Uri.fromFile(mFile); + mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); + mIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, durationLimit); + setActivityIntent(mIntent); + getActivity(); + + recordVideo(5000); + pressDone(); + + int duration = verify(getActivity(), uri); + // The duraion should be close to to the limit. The last video duration + // also has duration, so the total duration may exceeds the limit a + // little bit. + Log.v(TAG, "Video length is " + duration + " ms."); + assertTrue(duration < (durationLimit + 1) * 1000); + } + + @LargeTest + public void testExtraVideoQuality() throws Exception { + mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); + mFile2 = new File(Environment.getExternalStorageDirectory(), "video2.tmp"); + + Uri uri = Uri.fromFile(mFile); + mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); + mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); // low quality + setActivityIntent(mIntent); + getActivity(); + + recordVideo(); + pressDone(); + + verify(getActivity(), uri); + setActivity(null); + + uri = Uri.fromFile(mFile2); + mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); + mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // high quality + setActivityIntent(mIntent); + getActivity(); + + recordVideo(); + pressDone(); + + verify(getActivity(), uri); + assertTrue(mFile.length() <= mFile2.length()); + } + + // Verify result code, result data, and the duration. + private int verify(CameraActivity activity, Uri uri) throws Exception { + assertTrue(activity.isFinishing()); + assertEquals(Activity.RESULT_OK, activity.getResultCode()); + + // Verify the video file + MediaMetadataRetriever retriever = new MediaMetadataRetriever(); + retriever.setDataSource(activity, uri); + String duration = retriever.extractMetadata( + MediaMetadataRetriever.METADATA_KEY_DURATION); + assertNotNull(duration); + int durationValue = Integer.parseInt(duration); + Log.v(TAG, "Video duration is " + durationValue); + assertTrue(durationValue > 0); + return durationValue; + } + + private void recordVideo(int ms) throws Exception { + getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_CAMERA); + Thread.sleep(ms); + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + // If recording is in progress, stop it. Run these atomically in + // UI thread. + CameraActivity activity = getActivity(); + if (activity.isRecording()) { + activity.findViewById(R.id.shutter_button).performClick(); + } + } + }); + } + + private void recordVideo() throws Exception { + recordVideo(2000); + } + + private void pressDone() { + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + getActivity().findViewById(R.id.btn_done).performClick(); + } + }); + } + + private void pressCancel() { + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + getActivity().findViewById(R.id.btn_cancel).performClick(); + } + }); + } +} diff --git a/tests/src/com/android/gallery3d/stress/CameraLatency.java b/tests/src/com/android/gallery3d/stress/CameraLatency.java new file mode 100755 index 000000000..2cdc2f1b7 --- /dev/null +++ b/tests/src/com/android/gallery3d/stress/CameraLatency.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.stress; + +import com.android.camera.CameraActivity; + +import android.app.Instrumentation; +import android.os.Environment; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; +import android.view.KeyEvent; + +import java.io.BufferedWriter; +import java.io.FileWriter; + +/** + * Junit / Instrumentation test case for camera test + * + */ + +public class CameraLatency extends ActivityInstrumentationTestCase2 { + private String TAG = "CameraLatency"; + private static final int TOTAL_NUMBER_OF_IMAGECAPTURE = 20; + private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 4000; + private static final String CAMERA_TEST_OUTPUT_FILE = + Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; + + private long mTotalAutoFocusTime; + private long mTotalShutterLag; + private long mTotalShutterToPictureDisplayedTime; + private long mTotalPictureDisplayedToJpegCallbackTime; + private long mTotalJpegCallbackFinishTime; + private long mAvgAutoFocusTime; + private long mAvgShutterLag = mTotalShutterLag; + private long mAvgShutterToPictureDisplayedTime; + private long mAvgPictureDisplayedToJpegCallbackTime; + private long mAvgJpegCallbackFinishTime; + + public CameraLatency() { + super(CameraActivity.class); + } + + @Override + protected void setUp() throws Exception { + getActivity(); + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testImageCapture() { + Log.v(TAG, "start testImageCapture test"); + Instrumentation inst = getInstrumentation(); + inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); + try { + for (int i = 0; i < TOTAL_NUMBER_OF_IMAGECAPTURE; i++) { + Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); + inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); + Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); + //skip the first measurement + if (i != 0) { + CameraActivity c = getActivity(); + + // if any of the latency var accessor methods return -1 then the + // camera is set to a different module other than PhotoModule so + // skip the shot and try again + if (c.getAutoFocusTime() != -1) { + mTotalAutoFocusTime += c.getAutoFocusTime(); + mTotalShutterLag += c.getShutterLag(); + mTotalShutterToPictureDisplayedTime += + c.getShutterToPictureDisplayedTime(); + mTotalPictureDisplayedToJpegCallbackTime += + c.getPictureDisplayedToJpegCallbackTime(); + mTotalJpegCallbackFinishTime += c.getJpegCallbackFinishTime(); + } + else { + i--; + continue; + } + } + } + } catch (Exception e) { + Log.v(TAG, "Got exception", e); + } + //ToDO: yslau + //1) Need to get the baseline from the cupcake so that we can add the + //failure condition of the camera latency. + //2) Only count those number with succesful capture. Set the timer to invalid + //before capture and ignore them if the value is invalid + int numberofRun = TOTAL_NUMBER_OF_IMAGECAPTURE - 1; + mAvgAutoFocusTime = mTotalAutoFocusTime / numberofRun; + mAvgShutterLag = mTotalShutterLag / numberofRun; + mAvgShutterToPictureDisplayedTime = + mTotalShutterToPictureDisplayedTime / numberofRun; + mAvgPictureDisplayedToJpegCallbackTime = + mTotalPictureDisplayedToJpegCallbackTime / numberofRun; + mAvgJpegCallbackFinishTime = + mTotalJpegCallbackFinishTime / numberofRun; + + try { + FileWriter fstream = null; + fstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true); + BufferedWriter out = new BufferedWriter(fstream); + out.write("Camera Latency : \n"); + out.write("Number of loop: " + TOTAL_NUMBER_OF_IMAGECAPTURE + "\n"); + out.write("Avg AutoFocus = " + mAvgAutoFocusTime + "\n"); + out.write("Avg mShutterLag = " + mAvgShutterLag + "\n"); + out.write("Avg mShutterToPictureDisplayedTime = " + + mAvgShutterToPictureDisplayedTime + "\n"); + out.write("Avg mPictureDisplayedToJpegCallbackTime = " + + mAvgPictureDisplayedToJpegCallbackTime + "\n"); + out.write("Avg mJpegCallbackFinishTime = " + + mAvgJpegCallbackFinishTime + "\n"); + out.close(); + fstream.close(); + } catch (Exception e) { + fail("Camera Latency write output to file"); + } + Log.v(TAG, "The Image capture wait time = " + + WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); + Log.v(TAG, "Avg AutoFocus = " + mAvgAutoFocusTime); + Log.v(TAG, "Avg mShutterLag = " + mAvgShutterLag); + Log.v(TAG, "Avg mShutterToPictureDisplayedTime = " + + mAvgShutterToPictureDisplayedTime); + Log.v(TAG, "Avg mPictureDisplayedToJpegCallbackTime = " + + mAvgPictureDisplayedToJpegCallbackTime); + Log.v(TAG, "Avg mJpegCallbackFinishTime = " + mAvgJpegCallbackFinishTime); + } +} + diff --git a/tests/src/com/android/gallery3d/stress/CameraStartUp.java b/tests/src/com/android/gallery3d/stress/CameraStartUp.java new file mode 100644 index 000000000..3ca163227 --- /dev/null +++ b/tests/src/com/android/gallery3d/stress/CameraStartUp.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.stress; + +import com.android.camera.CameraActivity; + +import android.app.Activity; +import android.app.Instrumentation; +import android.content.Intent; +import android.os.Environment; +import android.provider.MediaStore; +import android.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; + +import java.io.FileWriter; +import java.io.BufferedWriter; + +/** + * Test cases to measure the camera and video recorder startup time. + */ +public class CameraStartUp extends InstrumentationTestCase { + + private static final int TOTAL_NUMBER_OF_STARTUP = 20; + + private String TAG = "CameraStartUp"; + private static final String CAMERA_TEST_OUTPUT_FILE = + Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; + private static int WAIT_TIME_FOR_PREVIEW = 1500; //1.5 second + + private long launchCamera() { + long startupTime = 0; + try { + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + long beforeStart = System.currentTimeMillis(); + Instrumentation inst = getInstrumentation(); + Activity cameraActivity = inst.startActivitySync(intent); + long cameraStarted = System.currentTimeMillis(); + Thread.sleep(WAIT_TIME_FOR_PREVIEW); + cameraActivity.finish(); + startupTime = cameraStarted - beforeStart; + Thread.sleep(1000); + Log.v(TAG, "camera startup time: " + startupTime); + } catch (Exception e) { + Log.v(TAG, "Got exception", e); + fail("Fails to get the output file"); + } + return startupTime; + } + + private long launchVideo() { + long startupTime = 0; + + try { + Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); + intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + long beforeStart = System.currentTimeMillis(); + Instrumentation inst = getInstrumentation(); + Activity recorderActivity = inst.startActivitySync(intent); + long cameraStarted = System.currentTimeMillis(); + recorderActivity.finish(); + startupTime = cameraStarted - beforeStart; + Log.v(TAG, "Video Startup Time = " + startupTime); + // wait for 1s to make sure it reach a clean stage + Thread.sleep(WAIT_TIME_FOR_PREVIEW); + Log.v(TAG, "video startup time: " + startupTime); + } catch (Exception e) { + Log.v(TAG, "Got exception", e); + fail("Fails to launch video output file"); + } + return startupTime; + } + + private void writeToOutputFile(long totalStartupTime, + String individualStartupTime, boolean firstStartUp, String Type) throws Exception { + // TODO (yslau) : Need to integrate the output data with central + // dashboard + try { + FileWriter fstream = null; + fstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true); + BufferedWriter out = new BufferedWriter(fstream); + if (firstStartUp) { + out.write("First " + Type + " Startup: " + totalStartupTime + "\n"); + } else { + long averageStartupTime = totalStartupTime / (TOTAL_NUMBER_OF_STARTUP -1); + out.write(Type + "startup time: " + "\n"); + out.write("Number of loop: " + (TOTAL_NUMBER_OF_STARTUP -1) + "\n"); + out.write(individualStartupTime + "\n\n"); + out.write(Type + " average startup time: " + averageStartupTime + " ms\n\n"); + } + out.close(); + fstream.close(); + } catch (Exception e) { + fail("Camera write output to file"); + } + } + + public void testLaunchVideo() throws Exception { + String individualStartupTime; + individualStartupTime = "Individual Video Startup Time = "; + long totalStartupTime = 0; + long startupTime = 0; + for (int i = 0; i < TOTAL_NUMBER_OF_STARTUP; i++) { + if (i == 0) { + // Capture the first startup time individually + long firstStartUpTime = launchVideo(); + writeToOutputFile(firstStartUpTime, "na", true, "Video"); + } else { + startupTime = launchVideo(); + totalStartupTime += startupTime; + individualStartupTime += startupTime + " ,"; + } + } + Log.v(TAG, "totalStartupTime =" + totalStartupTime); + writeToOutputFile(totalStartupTime, individualStartupTime, false, "Video"); + } + + public void testLaunchCamera() throws Exception { + String individualStartupTime; + individualStartupTime = "Individual Camera Startup Time = "; + long totalStartupTime = 0; + long startupTime = 0; + for (int i = 0; i < TOTAL_NUMBER_OF_STARTUP; i++) { + if (i == 0) { + // Capture the first startup time individually + long firstStartUpTime = launchCamera(); + writeToOutputFile(firstStartUpTime, "na", true, "Camera"); + } else { + startupTime = launchCamera(); + totalStartupTime += startupTime; + individualStartupTime += startupTime + " ,"; + } + } + Log.v(TAG, "totalStartupTime =" + totalStartupTime); + writeToOutputFile(totalStartupTime, + individualStartupTime, false, "Camera"); + } +} diff --git a/tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java b/tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java new file mode 100755 index 000000000..d3fb10dad --- /dev/null +++ b/tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.stress; + +import android.os.Bundle; +import android.test.InstrumentationTestRunner; +import android.test.InstrumentationTestSuite; +import junit.framework.TestSuite; + +public class CameraStressTestRunner extends InstrumentationTestRunner { + + // Default recorder settings + public static int mVideoDuration = 20000; // set default to 20 seconds + public static int mVideoIterations = 1; // set default to 1 video + public static int mImageIterations = 10; // set default to 10 images + + @Override + public TestSuite getAllTests() { + TestSuite suite = new InstrumentationTestSuite(this); + suite.addTestSuite(ImageCapture.class); + suite.addTestSuite(VideoCapture.class); + return suite; + } + + @Override + public ClassLoader getLoader() { + return CameraStressTestRunner.class.getClassLoader(); + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + String video_iterations = (String) icicle.get("video_iterations"); + String image_iterations = (String) icicle.get("image_iterations"); + String video_duration = (String) icicle.get("video_duration"); + + if ( video_iterations != null ) { + mVideoIterations = Integer.parseInt(video_iterations); + } + if ( image_iterations != null) { + mImageIterations = Integer.parseInt(image_iterations); + } + if ( video_duration != null) { + mVideoDuration = Integer.parseInt(video_duration); + } + } +} diff --git a/tests/src/com/android/gallery3d/stress/ImageCapture.java b/tests/src/com/android/gallery3d/stress/ImageCapture.java new file mode 100755 index 000000000..5a9ee6a6c --- /dev/null +++ b/tests/src/com/android/gallery3d/stress/ImageCapture.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.stress; + +import com.android.camera.CameraActivity; +import com.android.gallery3d.stress.CameraStressTestRunner; + +import android.app.Instrumentation; +import android.content.Intent; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; +import android.view.KeyEvent; +import android.app.Activity; + +/** + * Junit / Instrumentation test case for camera test + * + * Running the test suite: + * + * adb shell am instrument \ + * -e class com.android.camera.stress.ImageCapture \ + * -w com.google.android.camera.tests/android.test.InstrumentationTestRunner + * + */ + +public class ImageCapture extends ActivityInstrumentationTestCase2 { + private String TAG = "ImageCapture"; + private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 1500; //1.5 sedconds + private static final long WAIT_FOR_SWITCH_CAMERA = 3000; //3 seconds + + private TestUtil testUtil = new TestUtil(); + + // Private intent extras. + private final static String EXTRAS_CAMERA_FACING = + "android.intent.extras.CAMERA_FACING"; + + public ImageCapture() { + super(CameraActivity.class); + } + + @Override + protected void setUp() throws Exception { + testUtil.prepareOutputFile(); + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + testUtil.closeOutputFile(); + super.tearDown(); + } + + public void captureImages(String reportTag, Instrumentation inst) { + int total_num_of_images = CameraStressTestRunner.mImageIterations; + Log.v(TAG, "no of images = " + total_num_of_images); + + //TODO(yslau): Need to integrate the outoput with the central dashboard, + //write to a txt file as a temp solution + boolean memoryResult = false; + KeyEvent focusEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_FOCUS); + + try { + testUtil.writeReportHeader(reportTag, total_num_of_images); + for (int i = 0; i < total_num_of_images; i++) { + Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); + inst.sendKeySync(focusEvent); + inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA); + Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); + testUtil.writeResult(i); + } + } catch (Exception e) { + Log.v(TAG, "Got exception: " + e.toString()); + assertTrue("testImageCapture", false); + } + } + + public void testBackImageCapture() throws Exception { + Instrumentation inst = getInstrumentation(); + Intent intent = new Intent(); + + intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(EXTRAS_CAMERA_FACING, + android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK); + Activity act = inst.startActivitySync(intent); + Thread.sleep(WAIT_FOR_SWITCH_CAMERA); + captureImages("Back Camera Image Capture\n", inst); + act.finish(); + } + + public void testFrontImageCapture() throws Exception { + Instrumentation inst = getInstrumentation(); + Intent intent = new Intent(); + + intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(EXTRAS_CAMERA_FACING, + android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT); + Activity act = inst.startActivitySync(intent); + Thread.sleep(WAIT_FOR_SWITCH_CAMERA); + captureImages("Front Camera Image Capture\n", inst); + act.finish(); + } +} diff --git a/tests/src/com/android/gallery3d/stress/ShotToShotLatency.java b/tests/src/com/android/gallery3d/stress/ShotToShotLatency.java new file mode 100644 index 000000000..0d5749e7d --- /dev/null +++ b/tests/src/com/android/gallery3d/stress/ShotToShotLatency.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.stress; + +import android.app.Instrumentation; +import android.os.Environment; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; +import android.view.KeyEvent; +import com.android.camera.CameraActivity; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FilenameFilter; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; + +/** + * Junit / Instrumentation test case for measuring camera shot to shot latency + */ +public class ShotToShotLatency extends ActivityInstrumentationTestCase2 { + private String TAG = "ShotToShotLatency"; + private static final int TOTAL_NUMBER_OF_SNAPSHOTS = 250; + private static final long SNAPSHOT_WAIT = 1000; + private static final String CAMERA_TEST_OUTPUT_FILE = + Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; + private static final String CAMERA_IMAGE_DIRECTORY = + Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera/"; + + public ShotToShotLatency() { + super(CameraActivity.class); + } + + @Override + protected void setUp() throws Exception { + getActivity(); + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + private void cleanupLatencyImages() { + try { + File sdcard = new File(CAMERA_IMAGE_DIRECTORY); + File[] pics = null; + FilenameFilter filter = new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".jpg"); + } + }; + pics = sdcard.listFiles(filter); + for (File f : pics) { + f.delete(); + } + } catch (SecurityException e) { + Log.e(TAG, "Security manager access violation: " + e.toString()); + } + } + + private void sleep(long time) { + try { + Thread.sleep(time); + } catch (InterruptedException e) { + Log.e(TAG, "Sleep InterruptedException " + e.toString()); + } + } + + public void testShotToShotLatency() { + long sigmaOfDiffFromMeanSquared = 0; + double mean = 0; + double standardDeviation = 0; + ArrayList captureTimes = new ArrayList(); + ArrayList latencyTimes = new ArrayList(); + + Log.v(TAG, "start testShotToShotLatency test"); + Instrumentation inst = getInstrumentation(); + + // Generate data points + for (int i = 0; i < TOTAL_NUMBER_OF_SNAPSHOTS; i++) { + inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); + sleep(SNAPSHOT_WAIT); + CameraActivity c = getActivity(); + if (c.getCaptureStartTime() > 0) { + captureTimes.add(c.getCaptureStartTime()); + } + } + + // Calculate latencies + for (int j = 1; j < captureTimes.size(); j++) { + latencyTimes.add(captureTimes.get(j) - captureTimes.get(j - 1)); + } + + // Crunch numbers + for (long dataPoint : latencyTimes) { + mean += (double) dataPoint; + } + mean /= latencyTimes.size(); + + for (long dataPoint : latencyTimes) { + sigmaOfDiffFromMeanSquared += (dataPoint - mean) * (dataPoint - mean); + } + standardDeviation = Math.sqrt(sigmaOfDiffFromMeanSquared / latencyTimes.size()); + + // Report statistics + File outFile = new File(CAMERA_TEST_OUTPUT_FILE); + BufferedWriter output = null; + try { + output = new BufferedWriter(new FileWriter(outFile, true)); + output.write("Shot to shot latency - mean: " + mean + "\n"); + output.write("Shot to shot latency - standard deviation: " + standardDeviation + "\n"); + cleanupLatencyImages(); + } catch (IOException e) { + Log.e(TAG, "testShotToShotLatency IOException writing to log " + e.toString()); + } finally { + try { + if (output != null) { + output.close(); + } + } catch (IOException e) { + Log.e(TAG, "Error closing file: " + e.toString()); + } + } + } +} diff --git a/tests/src/com/android/gallery3d/stress/SwitchPreview.java b/tests/src/com/android/gallery3d/stress/SwitchPreview.java new file mode 100755 index 000000000..3545f3b3e --- /dev/null +++ b/tests/src/com/android/gallery3d/stress/SwitchPreview.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.stress; + +import com.android.camera.CameraActivity; + +import android.app.Instrumentation; +import android.content.Intent; +import android.provider.MediaStore; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.LargeTest; +import android.os.Environment; +import android.util.Log; + +import java.io.BufferedWriter; +import java.io.FileWriter; + +/** + * Junit / Instrumentation test case for camera test + * + * Running the test suite: + * + * adb shell am instrument \ + * -e class com.android.camera.stress.SwitchPreview \ + * -w com.android.camera.tests/com.android.camera.stress.CameraStressTestRunner + * + */ +public class SwitchPreview extends ActivityInstrumentationTestCase2 { + private String TAG = "SwitchPreview"; + private static final int TOTAL_NUMBER_OF_SWITCHING = 200; + private static final long WAIT_FOR_PREVIEW = 4000; + + private static final String CAMERA_TEST_OUTPUT_FILE = + Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; + private BufferedWriter mOut; + private FileWriter mfstream; + + public SwitchPreview() { + super(CameraActivity.class); + } + + @Override + protected void setUp() throws Exception { + getActivity(); + prepareOutputFile(); + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + getActivity().finish(); + closeOutputFile(); + super.tearDown(); + } + + private void prepareOutputFile(){ + try{ + mfstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true); + mOut = new BufferedWriter(mfstream); + } catch (Exception e){ + assertTrue("Camera Switch Mode", false); + } + } + + private void closeOutputFile() { + try { + mOut.write("\n"); + mOut.close(); + mfstream.close(); + } catch (Exception e) { + assertTrue("CameraSwitchMode close output", false); + } + } + + public void testSwitchMode() { + //Switching the video and the video recorder mode + Instrumentation inst = getInstrumentation(); + try{ + mOut.write("Camera Switch Mode:\n"); + mOut.write("No of loops :" + TOTAL_NUMBER_OF_SWITCHING + "\n"); + mOut.write("loop: "); + for (int i=0; i< TOTAL_NUMBER_OF_SWITCHING; i++) { + Thread.sleep(WAIT_FOR_PREVIEW); + Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.setClass(getInstrumentation().getTargetContext(), + CameraActivity.class); + getActivity().startActivity(intent); + Thread.sleep(WAIT_FOR_PREVIEW); + intent = new Intent(); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.setClass(getInstrumentation().getTargetContext(), + CameraActivity.class); + getActivity().startActivity(intent); + mOut.write(" ," + i); + mOut.flush(); + } + } catch (Exception e){ + Log.v(TAG, "Got exception", e); + } + } +} diff --git a/tests/src/com/android/gallery3d/stress/TestUtil.java b/tests/src/com/android/gallery3d/stress/TestUtil.java new file mode 100644 index 000000000..56ab715f7 --- /dev/null +++ b/tests/src/com/android/gallery3d/stress/TestUtil.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.stress; + +import android.os.Environment; +import java.io.FileWriter; +import java.io.BufferedWriter; + + +/** + * Collection of utility functions used for the test. + */ +public class TestUtil { + public BufferedWriter mOut; + public FileWriter mfstream; + + public TestUtil() { + } + + public void prepareOutputFile() throws Exception { + String camera_test_output_file = + Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; + mfstream = new FileWriter(camera_test_output_file, true); + mOut = new BufferedWriter(mfstream); + } + + public void closeOutputFile() throws Exception { + mOut.write("\n"); + mOut.close(); + mfstream.close(); + } + + public void writeReportHeader(String reportTag, int iteration) throws Exception { + mOut.write(reportTag); + mOut.write("No of loops :" + iteration + "\n"); + mOut.write("loop: "); + } + + public void writeResult(int iteration) throws Exception { + mOut.write(" ," + iteration); + mOut.flush(); + } +} diff --git a/tests/src/com/android/gallery3d/stress/VideoCapture.java b/tests/src/com/android/gallery3d/stress/VideoCapture.java new file mode 100755 index 000000000..8211badf7 --- /dev/null +++ b/tests/src/com/android/gallery3d/stress/VideoCapture.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.stress; + +import com.android.camera.CameraActivity; +import com.android.gallery3d.stress.TestUtil; + +import android.app.Activity; +import android.app.Instrumentation; +import android.content.Intent; +import android.provider.MediaStore; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.LargeTest; +import android.view.KeyEvent; + +import com.android.gallery3d.stress.CameraStressTestRunner; + +/** + * Junit / Instrumentation test case for camera test + * + * Running the test suite: + * + * adb shell am instrument \ + * -e class com.android.camera.stress.VideoCapture \ + * -w com.google.android.camera.tests/android.test.InstrumentationTestRunner + * + */ + +public class VideoCapture extends ActivityInstrumentationTestCase2 { + private static final long WAIT_FOR_PREVIEW = 1500; //1.5 seconds + private static final long WAIT_FOR_SWITCH_CAMERA = 3000; //2 seconds + + // Private intent extras which control the camera facing. + private final static String EXTRAS_CAMERA_FACING = + "android.intent.extras.CAMERA_FACING"; + + private TestUtil testUtil = new TestUtil(); + + public VideoCapture() { + super(CameraActivity.class); + } + + @Override + protected void setUp() throws Exception { + testUtil.prepareOutputFile(); + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + testUtil.closeOutputFile(); + super.tearDown(); + } + + public void captureVideos(String reportTag, Instrumentation inst) throws Exception{ + boolean memoryResult = false; + int total_num_of_videos = CameraStressTestRunner.mVideoIterations; + int video_duration = CameraStressTestRunner.mVideoDuration; + testUtil.writeReportHeader(reportTag, total_num_of_videos); + + for (int i = 0; i < total_num_of_videos; i++) { + Thread.sleep(WAIT_FOR_PREVIEW); + // record a video + inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA); + Thread.sleep(video_duration); + inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA); + testUtil.writeResult(i); + } + } + + public void testBackVideoCapture() throws Exception { + Instrumentation inst = getInstrumentation(); + Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); + + intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(EXTRAS_CAMERA_FACING, + android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK); + Activity act = inst.startActivitySync(intent); + Thread.sleep(WAIT_FOR_SWITCH_CAMERA); + captureVideos("Back Camera Video Capture\n", inst); + act.finish(); + } + + public void testFrontVideoCapture() throws Exception { + Instrumentation inst = getInstrumentation(); + Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); + + intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(EXTRAS_CAMERA_FACING, + android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT); + Activity act = inst.startActivitySync(intent); + Thread.sleep(WAIT_FOR_SWITCH_CAMERA); + captureVideos("Front Camera Video Capture\n", inst); + act.finish(); + } +} diff --git a/tests/src/com/android/gallery3d/unittest/CameraUnitTest.java b/tests/src/com/android/gallery3d/unittest/CameraUnitTest.java new file mode 100644 index 000000000..b8fb05fc2 --- /dev/null +++ b/tests/src/com/android/gallery3d/unittest/CameraUnitTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.unittest; + +import com.android.camera.Util; + +import android.graphics.Matrix; +import android.test.suitebuilder.annotation.SmallTest; + +import junit.framework.TestCase; + +@SmallTest +public class CameraUnitTest extends TestCase { + public void testRoundOrientation() { + int h = Util.ORIENTATION_HYSTERESIS; + assertEquals(0, Util.roundOrientation(0, 0)); + assertEquals(0, Util.roundOrientation(359, 0)); + assertEquals(0, Util.roundOrientation(0 + 44 + h, 0)); + assertEquals(90, Util.roundOrientation(0 + 45 + h, 0)); + assertEquals(0, Util.roundOrientation(360 - 44 - h, 0)); + assertEquals(270, Util.roundOrientation(360 - 45 - h, 0)); + + assertEquals(90, Util.roundOrientation(90, 90)); + assertEquals(90, Util.roundOrientation(90 + 44 + h, 90)); + assertEquals(180, Util.roundOrientation(90 + 45 + h, 90)); + assertEquals(90, Util.roundOrientation(90 - 44 - h, 90)); + assertEquals(0, Util.roundOrientation(90 - 45 - h, 90)); + + assertEquals(180, Util.roundOrientation(180, 180)); + assertEquals(180, Util.roundOrientation(180 + 44 + h, 180)); + assertEquals(270, Util.roundOrientation(180 + 45 + h, 180)); + assertEquals(180, Util.roundOrientation(180 - 44 - h, 180)); + assertEquals(90, Util.roundOrientation(180 - 45 - h, 180)); + + assertEquals(270, Util.roundOrientation(270, 270)); + assertEquals(270, Util.roundOrientation(270 + 44 + h, 270)); + assertEquals(0, Util.roundOrientation(270 + 45 + h, 270)); + assertEquals(270, Util.roundOrientation(270 - 44 - h, 270)); + assertEquals(180, Util.roundOrientation(270 - 45 - h, 270)); + + assertEquals(90, Util.roundOrientation(90, 0)); + assertEquals(180, Util.roundOrientation(180, 0)); + assertEquals(270, Util.roundOrientation(270, 0)); + + assertEquals(0, Util.roundOrientation(0, 90)); + assertEquals(180, Util.roundOrientation(180, 90)); + assertEquals(270, Util.roundOrientation(270, 90)); + + assertEquals(0, Util.roundOrientation(0, 180)); + assertEquals(90, Util.roundOrientation(90, 180)); + assertEquals(270, Util.roundOrientation(270, 180)); + + assertEquals(0, Util.roundOrientation(0, 270)); + assertEquals(90, Util.roundOrientation(90, 270)); + assertEquals(180, Util.roundOrientation(180, 270)); + } + + public void testPrepareMatrix() { + Matrix matrix = new Matrix(); + float[] points; + int[] expected; + + Util.prepareMatrix(matrix, false, 0, 800, 480); + points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250}; + expected = new int[] {0, 0, 400, 240, 800, 480, 400, 480, 100, 300}; + matrix.mapPoints(points); + assertEquals(expected, points); + + Util.prepareMatrix(matrix, false, 90, 800, 480); + points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250}; + expected = new int[] {800, 0, 400, 240, 0, 480, 0, 240, 300, 60}; + matrix.mapPoints(points); + assertEquals(expected, points); + + Util.prepareMatrix(matrix, false, 180, 800, 480); + points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250}; + expected = new int[] {800, 480, 400, 240, 0, 0, 400, 0, 700, 180}; + matrix.mapPoints(points); + assertEquals(expected, points); + + Util.prepareMatrix(matrix, true, 180, 800, 480); + points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250}; + expected = new int[] {0, 480, 400, 240, 800, 0, 400, 0, 100, 180}; + matrix.mapPoints(points); + assertEquals(expected, points); + } + + private void assertEquals(int expected[], float[] actual) { + for (int i = 0; i < expected.length; i++) { + assertEquals("Array index " + i + " mismatch", expected[i], Math.round(actual[i])); + } + } +} -- cgit v1.2.3