1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view.cts; 18 19 import static org.junit.Assert.assertTrue; 20 21 import android.Manifest; 22 import android.content.Context; 23 import android.hardware.display.DisplayManager; 24 import android.os.Handler; 25 import android.os.Looper; 26 import android.os.SystemClock; 27 import android.util.Log; 28 import android.view.Display; 29 import android.view.WindowManager; 30 31 import androidx.test.filters.LargeTest; 32 import androidx.test.platform.app.InstrumentationRegistry; 33 import androidx.test.rule.ActivityTestRule; 34 import androidx.test.runner.AndroidJUnit4; 35 36 import com.android.compatibility.common.util.AdoptShellPermissionsRule; 37 38 import org.junit.After; 39 import org.junit.Before; 40 import org.junit.Rule; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 44 import java.util.concurrent.CountDownLatch; 45 import java.util.concurrent.TimeUnit; 46 47 /** 48 * Test that the screen refresh rate claimed by 49 * android.view.Display.getRefreshRate() matches the steady-state framerate 50 * achieved by vsync-limited eglSwapBuffers(). The primary goal is to test 51 * Display.getRefreshRate() -- using GL is just an easy and hopefully reliable 52 * way of measuring the actual refresh rate. 53 */ 54 @LargeTest 55 @RunWith(AndroidJUnit4.class) 56 public class DisplayRefreshRateTest { 57 // The test passes if 58 // abs(measured_fps - Display.getRefreshRate()) <= FPS_TOLERANCE. 59 // A smaller tolerance requires a more accurate measured_fps in order 60 // to avoid false negatives. 61 private static final float FPS_TOLERANCE = 2.0f; 62 63 private static final String TAG = "DisplayRefreshRateTest"; 64 65 private DisplayManager mDisplayManager; 66 67 private Display mDisplay; 68 69 private int mInitialMatchContentFrameRate; 70 71 private final DisplayListener mDisplayListener = new DisplayListener(); 72 73 private DisplayRefreshRateCtsActivity mActivity; 74 private DisplayRefreshRateCtsActivity.FpsResult mFpsResult; 75 76 @Rule 77 public ActivityTestRule<DisplayRefreshRateCtsActivity> mActivityRule = 78 new ActivityTestRule<>(DisplayRefreshRateCtsActivity.class); 79 80 @Rule 81 public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule( 82 InstrumentationRegistry.getInstrumentation().getUiAutomation(), 83 Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS, 84 Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE); 85 86 class DisplayListener implements DisplayManager.DisplayListener { 87 private CountDownLatch mCountDownLatch = new CountDownLatch(1); 88 waitForModeToChange(int modeId)89 void waitForModeToChange(int modeId) throws InterruptedException { 90 while (modeId != mDisplay.getMode().getModeId()) { 91 mCountDownLatch.await(5, TimeUnit.SECONDS); 92 } 93 } 94 95 @Override onDisplayAdded(int displayId)96 public void onDisplayAdded(int displayId) { 97 98 } 99 100 @Override onDisplayRemoved(int displayId)101 public void onDisplayRemoved(int displayId) { 102 103 } 104 105 @Override onDisplayChanged(int displayId)106 public void onDisplayChanged(int displayId) { 107 if (displayId != mDisplay.getDisplayId()) { 108 return; 109 } 110 111 mCountDownLatch.countDown(); 112 } 113 } 114 115 116 @Before setup()117 public void setup() throws InterruptedException { 118 mActivity = mActivityRule.getActivity(); 119 mFpsResult = mActivity.getFpsResult(); 120 121 Context context = mActivity.getApplicationContext(); 122 mDisplayManager = context.getSystemService(DisplayManager.class); 123 124 mInitialMatchContentFrameRate = 125 toSwitchingType(mDisplayManager.getMatchContentFrameRateUserPreference()); 126 mDisplayManager.setRefreshRateSwitchingType(DisplayManager.SWITCHING_TYPE_NONE); 127 mDisplayManager.setShouldAlwaysRespectAppRequestedMode(true); 128 129 // This tests the fps of the default display. 130 // In consideration of multi-display devices we use getApplicationContext() 131 // to get the default display. 132 WindowManager wm = context.getSystemService(WindowManager.class); 133 mDisplay = wm.getDefaultDisplay(); 134 135 mDisplayManager.registerDisplayListener(mDisplayListener, 136 new Handler(Looper.getMainLooper())); 137 138 int highestRefreshRateModeId = getHighestRefreshRateModeId(); 139 mActivity.setModeId(highestRefreshRateModeId); 140 mDisplayListener.waitForModeToChange(highestRefreshRateModeId); 141 } 142 getHighestRefreshRateModeId()143 private int getHighestRefreshRateModeId() { 144 int highestRefreshRateModeId = mDisplay.getMode().getModeId(); 145 for (Display.Mode mode : mDisplay.getSupportedModes()) { 146 if (mode.getPhysicalHeight() != mDisplay.getMode().getPhysicalHeight()) { 147 continue; 148 } 149 150 if (mode.getPhysicalWidth() != mDisplay.getMode().getPhysicalWidth()) { 151 continue; 152 } 153 154 if (mode.getRefreshRate() > mDisplay.getMode().getRefreshRate()) { 155 highestRefreshRateModeId = mode.getModeId(); 156 } 157 } 158 return highestRefreshRateModeId; 159 } 160 161 @After tearDown()162 public void tearDown() { 163 mDisplayManager.setRefreshRateSwitchingType(mInitialMatchContentFrameRate); 164 mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false); 165 } 166 167 @Test testRefreshRate()168 public void testRefreshRate() { 169 boolean fpsOk = false; 170 float claimedFps = mDisplay.getRefreshRate(); 171 172 for (int i = 0; i < 3; i++) { 173 float achievedFps = mFpsResult.waitResult(); 174 Log.d(TAG, "claimed " + claimedFps + " fps, " + 175 "achieved " + achievedFps + " fps"); 176 fpsOk = Math.abs(claimedFps - achievedFps) <= FPS_TOLERANCE; 177 if (fpsOk) { 178 break; 179 } else { 180 // it could be other activity like bug report capturing for other failures 181 // sleep for a while and re-try 182 SystemClock.sleep(10000); 183 mFpsResult.restart(); 184 } 185 } 186 mActivity.finish(); 187 assertTrue(fpsOk); 188 } 189 toSwitchingType(int matchContentFrameRateUserPreference)190 private static int toSwitchingType(int matchContentFrameRateUserPreference) { 191 switch (matchContentFrameRateUserPreference) { 192 case DisplayManager.MATCH_CONTENT_FRAMERATE_NEVER: 193 return DisplayManager.SWITCHING_TYPE_NONE; 194 case DisplayManager.MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY: 195 return DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS; 196 case DisplayManager.MATCH_CONTENT_FRAMERATE_ALWAYS: 197 return DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS; 198 default: 199 return -1; 200 } 201 } 202 } 203