1ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu/*
2ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu * Copyright (C) 2012 The Android Open Source Project
3ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu *
4ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu * Licensed under the Apache License, Version 2.0 (the "License");
5ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu * you may not use this file except in compliance with the License.
6ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu * You may obtain a copy of the License at
7ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu *
8ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu *      http://www.apache.org/licenses/LICENSE-2.0
9ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu *
10ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu * Unless required by applicable law or agreed to in writing, software
11ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu * distributed under the License is distributed on an "AS IS" BASIS,
12ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu * See the License for the specific language governing permissions and
14ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu * limitations under the License.
15ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu */
16ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
17ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liupackage com.android.camera.stress;
18ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
19ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport android.app.Instrumentation;
20ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport android.os.Environment;
21ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport android.test.ActivityInstrumentationTestCase2;
22ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport android.test.suitebuilder.annotation.LargeTest;
23ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport android.util.Log;
24ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport android.view.KeyEvent;
25ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport com.android.camera.CameraActivity;
26ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport java.io.BufferedWriter;
27ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport java.io.File;
28ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport java.io.FilenameFilter;
29ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport java.io.FileWriter;
30ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport java.io.IOException;
31ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liuimport java.util.ArrayList;
32ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
33ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu/**
34ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu * Junit / Instrumentation test case for measuring camera shot to shot latency
35ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu */
36ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liupublic class ShotToShotLatency extends ActivityInstrumentationTestCase2<CameraActivity> {
37ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    private String TAG = "ShotToShotLatency";
38ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    private static final int TOTAL_NUMBER_OF_SNAPSHOTS = 250;
39ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    private static final long SNAPSHOT_WAIT = 1000;
40ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    private static final String CAMERA_TEST_OUTPUT_FILE =
41ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt";
42ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    private static final String CAMERA_IMAGE_DIRECTORY =
43ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera/";
44ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
45ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    public ShotToShotLatency() {
46ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        super(CameraActivity.class);
47ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    }
48ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
49ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    @Override
50ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    protected void setUp() throws Exception {
51ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        getActivity();
52ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        super.setUp();
53ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    }
54ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
55ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    @Override
56ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    protected void tearDown() throws Exception {
57ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        super.tearDown();
58ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    }
59ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
60ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    private void cleanupLatencyImages() {
61ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        try {
62ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            File sdcard = new File(CAMERA_IMAGE_DIRECTORY);
63ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            File[] pics = null;
64ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            FilenameFilter filter = new FilenameFilter() {
65ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu                public boolean accept(File dir, String name) {
66ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu                    return name.endsWith(".jpg");
67ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu                }
68ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            };
69ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            pics = sdcard.listFiles(filter);
70ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            for (File f : pics) {
71ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu                f.delete();
72ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            }
73ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        } catch (SecurityException e) {
74ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            Log.e(TAG, "Security manager access violation: " + e.toString());
75ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        }
76ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    }
77ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
78ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    private void sleep(long time) {
79ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        try {
80ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            Thread.sleep(time);
81ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        } catch (InterruptedException e) {
82ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            Log.e(TAG, "Sleep InterruptedException " + e.toString());
83ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        }
84ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    }
85ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
86ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    @LargeTest
87ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    public void testShotToShotLatency() {
88ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        long sigmaOfDiffFromMeanSquared = 0;
89ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        double mean = 0;
90ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        double standardDeviation = 0;
91ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        ArrayList<Long> captureTimes = new ArrayList<Long>();
92ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        ArrayList<Long> latencyTimes = new ArrayList<Long>();
93ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
94ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        Log.v(TAG, "start testShotToShotLatency test");
95ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        Instrumentation inst = getInstrumentation();
96ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
97ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        // Generate data points
98ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        for (int i = 0; i < TOTAL_NUMBER_OF_SNAPSHOTS; i++) {
99ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
100ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            sleep(SNAPSHOT_WAIT);
101ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            CameraActivity c = getActivity();
102ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            if (c.getCaptureStartTime() > 0) {
103ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu                captureTimes.add(c.getCaptureStartTime());
104ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            }
105ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        }
106ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
107ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        // Calculate latencies
108ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        for (int j = 1; j < captureTimes.size(); j++) {
109ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            latencyTimes.add(captureTimes.get(j) - captureTimes.get(j - 1));
110ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        }
111ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
112ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        // Crunch numbers
113ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        for (long dataPoint : latencyTimes) {
114ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            mean += (double) dataPoint;
115ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        }
116ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        mean /= latencyTimes.size();
117ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
118ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        for (long dataPoint : latencyTimes) {
119ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            sigmaOfDiffFromMeanSquared += (dataPoint - mean) * (dataPoint - mean);
120ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        }
121ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        standardDeviation = Math.sqrt(sigmaOfDiffFromMeanSquared / latencyTimes.size());
122ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu
123ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        // Report statistics
124ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        File outFile = new File(CAMERA_TEST_OUTPUT_FILE);
125ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        BufferedWriter output = null;
126ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        try {
127ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            output = new BufferedWriter(new FileWriter(outFile, true));
128ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            output.write("Shot to shot latency - mean: " + mean + "\n");
129ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            output.write("Shot to shot latency - standard deviation: " + standardDeviation + "\n");
130ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            cleanupLatencyImages();
131ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        } catch (IOException e) {
132ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            Log.e(TAG, "testShotToShotLatency IOException writing to log " + e.toString());
133ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        } finally {
134ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            try {
135ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu                if (output != null) {
136ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu                    output.close();
137ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu                }
138ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            } catch (IOException e) {
139ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu                Log.e(TAG, "Error closing file: " + e.toString());
140ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu            }
141ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu        }
142ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu    }
143ffa6237aed496373cd578ccdb9d2a47cde90e25dDoris Liu}
144