• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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