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