Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / public / android / javatests / src / org / chromium / content / browser / VSyncMonitorTest.java
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.content.browser;
6
7 import android.content.Context;
8 import android.os.SystemClock;
9 import android.test.InstrumentationTestCase;
10 import android.test.suitebuilder.annotation.MediumTest;
11
12 import org.chromium.base.ThreadUtils;
13 import org.chromium.ui.VSyncMonitor;
14
15 import java.util.Arrays;
16 import java.util.concurrent.Callable;
17
18 public class VSyncMonitorTest extends InstrumentationTestCase {
19     private static class VSyncDataCollector implements VSyncMonitor.Listener {
20         public long mFramePeriods[];
21         public int mFrameCount;
22         public long mLastVSyncCpuTimeMillis;
23
24         private final boolean mActivelyRequestUpdate;
25         private boolean mDone;
26         private long mPreviousVSyncTimeMicros;
27         private Object mSyncRoot = new Object();
28
29         VSyncDataCollector(int frames, boolean activelyRequestUpdate) {
30             mFramePeriods = new long[frames];
31             mActivelyRequestUpdate = activelyRequestUpdate;
32         }
33
34         public boolean isDone() {
35             synchronized (mSyncRoot) {
36                 return mDone;
37             }
38         }
39
40         @Override
41         public void onVSync(VSyncMonitor monitor, long vsyncTimeMicros) {
42             mLastVSyncCpuTimeMillis = SystemClock.uptimeMillis();
43             if (mPreviousVSyncTimeMicros == 0) {
44                 mPreviousVSyncTimeMicros = vsyncTimeMicros;
45                 return;
46             }
47             if (mFrameCount >= mFramePeriods.length) {
48                 synchronized (mSyncRoot) {
49                     mDone = true;
50                     mSyncRoot.notify();
51                 }
52                 return;
53             }
54             mFramePeriods[mFrameCount++] = vsyncTimeMicros - mPreviousVSyncTimeMicros;
55             mPreviousVSyncTimeMicros = vsyncTimeMicros;
56             if (mActivelyRequestUpdate) monitor.requestUpdate();
57         }
58
59         public void waitTillDone() throws InterruptedException {
60             synchronized (mSyncRoot) {
61                 while (!isDone()) {
62                     mSyncRoot.wait();
63                 }
64             }
65         }
66     }
67
68     // The vsync monitor must be created on the UI thread to avoid associating the underlying
69     // Choreographer with the Looper from the test runner thread.
70     private VSyncMonitor createVSyncMonitor(
71             final VSyncMonitor.Listener listener, final boolean enableJBVSync) {
72         return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<VSyncMonitor>() {
73             @Override
74             public VSyncMonitor call() {
75                 Context context = getInstrumentation().getContext();
76                 return new VSyncMonitor(context, listener, enableJBVSync);
77             }
78         });
79     }
80
81     // Check that the vsync period roughly matches the timestamps that the monitor generates.
82     private void performVSyncPeriodTest(boolean enableJBVSync) throws InterruptedException {
83         // Collect roughly one second of data on a 60 fps display.
84         collectAndCheckVSync(enableJBVSync, 60, true);
85         collectAndCheckVSync(enableJBVSync, VSyncMonitor.MAX_AUTO_ONVSYNC_COUNT, false);
86     }
87
88     private void collectAndCheckVSync(
89             boolean enableJBVSync, final int totalFrames, final boolean activeFrames)
90             throws InterruptedException {
91         VSyncDataCollector collector = new VSyncDataCollector(totalFrames, activeFrames);
92         VSyncMonitor monitor = createVSyncMonitor(collector, enableJBVSync);
93
94         long reportedFramePeriod = monitor.getVSyncPeriodInMicroseconds();
95         assertTrue(reportedFramePeriod > 0);
96
97         assertFalse(collector.isDone());
98         monitor.requestUpdate();
99         collector.waitTillDone();
100         assertTrue(collector.isDone());
101         monitor.stop();
102
103         // Check that the median frame rate is within 10% of the reported frame period.
104         assertTrue(collector.mFrameCount == totalFrames);
105         Arrays.sort(collector.mFramePeriods, 0, collector.mFramePeriods.length);
106         long medianFramePeriod = collector.mFramePeriods[collector.mFramePeriods.length / 2];
107         if (Math.abs(medianFramePeriod - reportedFramePeriod) > reportedFramePeriod * .1) {
108             fail("Measured median frame period " + medianFramePeriod
109                     + " differs by more than 10% from the reported frame period "
110                     + reportedFramePeriod + " for "
111                     + (activeFrames ? "requested" : "automatically sent") + " frames");
112         }
113     }
114
115     // Check that the vsync period roughly matches the timestamps that the monitor generates.
116     @MediumTest
117     public void testVSyncPeriodAllowJBVSync() throws InterruptedException {
118         performVSyncPeriodTest(true);
119     }
120
121     // Check that the vsync period roughly matches the timestamps that the monitor generates.
122     @MediumTest
123     public void testVSyncPeriodDisallowJBVSync() throws InterruptedException {
124         performVSyncPeriodTest(false);
125     }
126
127     // Check that the vsync period roughly matches the timestamps that the monitor generates.
128     private void performVSyncActivationFromIdle(boolean enableJBVSync) throws InterruptedException {
129         VSyncDataCollector collector = new VSyncDataCollector(1, false);
130         VSyncMonitor monitor = createVSyncMonitor(collector, enableJBVSync);
131
132         monitor.requestUpdate();
133         collector.waitTillDone();
134         assertTrue(collector.isDone());
135         monitor.stop();
136
137         long period = monitor.getVSyncPeriodInMicroseconds() / 1000;
138         long delay = SystemClock.uptimeMillis() - collector.mLastVSyncCpuTimeMillis;
139
140         // The VSync should have activated immediately instead of at the next real vsync.
141         assertTrue(delay < period);
142     }
143
144     @MediumTest
145     public void testVSyncActivationFromIdleAllowJBVSync() throws InterruptedException {
146         performVSyncActivationFromIdle(true);
147     }
148
149     @MediumTest
150     public void testVSyncActivationFromIdleDisallowJBVSync() throws InterruptedException {
151         performVSyncActivationFromIdle(false);
152     }
153 }