| /* |
| * 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 android.view.cts; |
| |
| import android.content.Context; |
| import android.opengl.GLSurfaceView; |
| import android.test.ActivityInstrumentationTestCase2; |
| import android.test.UiThreadTest; |
| import android.view.Display; |
| import android.view.WindowManager; |
| import android.util.Log; |
| |
| import java.lang.InterruptedException; |
| import java.lang.Thread; |
| import java.util.ArrayList; |
| import javax.microedition.khronos.egl.EGLConfig; |
| import javax.microedition.khronos.opengles.GL10; |
| |
| /** |
| * Test that the screen refresh rate claimed by |
| * android.view.Display.getRefreshRate() matches the steady-state framerate |
| * achieved by vsync-limited eglSwapBuffers(). The primary goal is to test |
| * Display.getRefreshRate() -- using GL is just an easy and hopefully reliable |
| * way of measuring the actual refresh rate. |
| */ |
| public class DisplayRefreshRateTest extends |
| ActivityInstrumentationTestCase2<GLSurfaceViewCtsActivity> { |
| |
| // The test passes if |
| // abs(measured_fps - Display.getRefreshRate()) <= FPS_TOLERANCE. |
| // A smaller tolerance requires a more accurate measured_fps in order |
| // to avoid false negatives. |
| private static final float FPS_TOLERANCE = 2.0f; |
| |
| private static final String TAG = "DisplayRefreshRateTest"; |
| |
| private class FpsResult { |
| private float mFps; |
| private boolean mValid = false; |
| private boolean mRestartRequested = false; |
| |
| public final synchronized void notifyResult(float fps) { |
| if (!mValid) { |
| mFps = fps; |
| mValid = true; |
| notifyAll(); |
| } |
| } |
| |
| public final synchronized float waitResult() { |
| while (!mValid) { |
| try { |
| wait(); |
| } catch (InterruptedException e) {/* ignore and retry */} |
| } |
| return mFps; |
| } |
| |
| public synchronized void restart() { |
| mRestartRequested = true; |
| mValid = false; |
| } |
| public synchronized boolean restartNecessary() { |
| return mRestartRequested; |
| } |
| public synchronized void ackRestart() { |
| mRestartRequested = false; |
| } |
| } |
| |
| private class Renderer implements GLSurfaceView.Renderer { |
| // Measurement knobs. |
| // NB: Some devices need a surprisingly long warmup period before the |
| // framerate becomes stable. |
| private static final float WARMUP_SECONDS = 2.0f; |
| private static final float TEST_SECONDS = 8.0f; |
| |
| // Test states |
| private static final int STATE_START = 0; |
| private static final int STATE_WARMUP = 1; |
| private static final int STATE_TEST = 2; |
| private static final int STATE_DONE = 3; |
| |
| private FpsResult mResult; |
| private int mState = STATE_START; |
| private float mStartTime = 0.0f; |
| private int mNumFrames = 0; |
| |
| public Renderer(FpsResult result) { |
| mResult = result; |
| } |
| |
| public void onDrawFrame(GL10 gl) { |
| float t = (float)System.nanoTime() * 1.0e-9f; |
| switch (mState) { |
| case STATE_START: |
| mStartTime = t; |
| mState = STATE_WARMUP; |
| break; |
| |
| case STATE_WARMUP: |
| if ((t - mStartTime) >= WARMUP_SECONDS) { |
| mStartTime = t; |
| mNumFrames = 0; |
| mState = STATE_TEST; |
| } |
| break; |
| |
| case STATE_TEST: |
| mNumFrames++; |
| float elapsed = t - mStartTime; |
| if (elapsed >= TEST_SECONDS) { |
| mResult.notifyResult((float)mNumFrames / elapsed); |
| mState = STATE_DONE; |
| } |
| break; |
| |
| case STATE_DONE: |
| if (mResult.restartNecessary()) { |
| mResult.ackRestart(); |
| mState = STATE_START; |
| Log.d(TAG, "restarting"); |
| } |
| break; |
| } |
| |
| // prevent unwanted optimizations or hidden costs (e.g. reading |
| // previous frame on tilers). |
| gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
| gl.glClear(gl.GL_COLOR_BUFFER_BIT); |
| } |
| |
| public void onSurfaceChanged(GL10 gl, int width, int height) { |
| // Do nothing. |
| } |
| |
| public void onSurfaceCreated(GL10 gl, EGLConfig config) { |
| // Do nothing. |
| } |
| } |
| |
| private FpsResult mResult; |
| |
| public DisplayRefreshRateTest() { |
| super(GLSurfaceViewCtsActivity.class); |
| mResult = new FpsResult(); |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| GLSurfaceViewCtsActivity.setRenderer(new Renderer(mResult)); |
| GLSurfaceViewCtsActivity.setRenderMode( |
| GLSurfaceView.RENDERMODE_CONTINUOUSLY); |
| } |
| |
| public void testRefreshRate() throws java.lang.InterruptedException { |
| boolean fpsOk = false; |
| GLSurfaceViewCtsActivity activity = getActivity(); |
| |
| WindowManager wm = (WindowManager)activity |
| .getView() |
| .getContext() |
| .getSystemService(Context.WINDOW_SERVICE); |
| Display dpy = wm.getDefaultDisplay(); |
| float claimedFps = dpy.getRefreshRate(); |
| |
| for (int i = 0; i < 3; i++) { |
| float achievedFps = mResult.waitResult(); |
| Log.d(TAG, "claimed " + claimedFps + " fps, " + |
| "achieved " + achievedFps + " fps"); |
| fpsOk = Math.abs(claimedFps - achievedFps) <= FPS_TOLERANCE; |
| if (fpsOk) { |
| break; |
| } else { |
| // it could be other sctivity like bug report capturing for other failures |
| // sleep for a while and re-try |
| Thread.sleep(10000); |
| mResult.restart(); |
| } |
| } |
| activity.finish(); |
| assertTrue(fpsOk); |
| } |
| |
| } |