Loading core/java/android/view/SurfaceControl.java +56 −0 Original line number Diff line number Diff line Loading @@ -263,6 +263,8 @@ public final class SurfaceControl implements Parcelable { long nativeObject, int compatibility); private static native void nativeSetFrameRateCategory( long transactionObj, long nativeObject, int category); private static native void nativeSetFrameRateSelectionStrategy( long transactionObj, long nativeObject, int strategy); private static native long nativeGetHandle(long nativeObject); private static native void nativeSetFixedTransformHint(long transactionObj, long nativeObject, Loading Loading @@ -850,6 +852,35 @@ public final class SurfaceControl implements Parcelable { */ public static final int METADATA_GAME_MODE = 8; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"FRAME_RATE_SELECTION_STRATEGY_"}, value = {FRAME_RATE_SELECTION_STRATEGY_SELF, FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN}) public @interface FrameRateSelectionStrategy {} // From window.h. Keep these in sync. /** * Default value. The layer uses its own frame rate specifications, assuming it has any * specifications, instead of its parent's. * However, {@link #FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN} on an ancestor layer * supersedes this behavior, meaning that this layer will inherit the frame rate specifications * of that ancestor layer. * @hide */ public static final int FRAME_RATE_SELECTION_STRATEGY_SELF = 0; /** * The layer's frame rate specifications will propagate to and override those of its descendant * layers. * The layer with this strategy has the {@link #FRAME_RATE_SELECTION_STRATEGY_SELF} behavior * for itself. This does mean that any parent or ancestor layer that also has the strategy * {@link FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN} will override this layer's * frame rate specifications. * @hide */ public static final int FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN = 1; /** * Builder class for {@link SurfaceControl} objects. * Loading Loading @@ -3668,6 +3699,31 @@ public final class SurfaceControl implements Parcelable { return this; } /** * Sets the frame rate selection strategy for the {@link SurfaceControl}. * * This instructs the system on how to choose a display refresh rate, following the * strategy for the layer's frame rate specifications relative to other layers'. * * @param sc The SurfaceControl to specify the frame rate category of. * @param strategy The frame rate selection strategy. * * @return This transaction object. * * @see #setFrameRate(SurfaceControl, float, int, int) * @see #setFrameRateCategory(SurfaceControl, int) * @see #setDefaultFrameRateCompatibility(SurfaceControl, int) * * @hide */ @NonNull public Transaction setFrameRateSelectionStrategy( @NonNull SurfaceControl sc, @FrameRateSelectionStrategy int strategy) { checkPreconditions(sc); nativeSetFrameRateSelectionStrategy(mNativeObject, sc.mNativeObject, strategy); return this; } /** * Sets focus on the window identified by the input {@code token} if the window is focusable * otherwise the request is dropped. Loading core/jni/android_view_SurfaceControl.cpp +9 −0 Original line number Diff line number Diff line Loading @@ -967,6 +967,13 @@ static void nativeSetFrameRateCategory(JNIEnv* env, jclass clazz, jlong transact transaction->setFrameRateCategory(ctrl, static_cast<int8_t>(category)); } static void nativeSetFrameRateSelectionStrategy(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jint strategy) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); const auto ctrl = reinterpret_cast<SurfaceControl*>(nativeObject); transaction->setFrameRateSelectionStrategy(ctrl, static_cast<int8_t>(strategy)); } static void nativeSetFixedTransformHint(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jint transformHint) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); Loading Loading @@ -2173,6 +2180,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetDefaultFrameRateCompatibility}, {"nativeSetFrameRateCategory", "(JJI)V", (void*)nativeSetFrameRateCategory}, {"nativeSetFrameRateSelectionStrategy", "(JJI)V", (void*)nativeSetFrameRateSelectionStrategy}, {"nativeSetDisplaySurface", "(JLandroid/os/IBinder;J)V", (void*)nativeSetDisplaySurface }, {"nativeSetDisplayLayerStack", "(JLandroid/os/IBinder;I)V", Loading tests/CtsSurfaceControlTestsStaging/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ android_test { "androidx.test.rules", "compatibility-device-util-axt", "com.google.android.material_material", "SurfaceFlingerProperties", "truth-prebuilt", ], resource_dirs: ["src/main/res"], Loading tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/GraphicsActivity.java +128 −7 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.hardware.display.DisplayManager; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.sysprop.SurfaceFlingerProperties; import android.util.Log; import android.view.Display; import android.view.Surface; Loading @@ -45,6 +46,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; /** * An Activity to help with frame rate testing. Loading Loading @@ -217,6 +219,27 @@ public class GraphicsActivity extends Activity { postBuffer(); } Surface getSurface() { return mSurface; } SurfaceControl getSurfaceControl() { return mSurfaceControl; } public int setFrameRate(float frameRate) { Log.i(TAG, String.format("Setting frame rate for %s: frameRate=%.2f", mName, frameRate)); int rc = 0; try (SurfaceControl.Transaction transaction = new SurfaceControl.Transaction()) { transaction.setFrameRate( mSurfaceControl, frameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT); transaction.apply(); } return rc; } public int setFrameRateCategory(int category) { Log.i(TAG, String.format( Loading @@ -230,6 +253,19 @@ public class GraphicsActivity extends Activity { return rc; } public int setFrameRateSelectionStrategy(int strategy) { Log.i(TAG, String.format("Setting frame rate selection strategy for %s: strategy=%d", mName, strategy)); int rc = 0; try (SurfaceControl.Transaction transaction = new SurfaceControl.Transaction()) { transaction.setFrameRateSelectionStrategy(mSurfaceControl, strategy); transaction.apply(); } return rc; } public void setVisibility(boolean visible) { Log.i(TAG, String.format("Setting visibility for %s: %s", mName, Loading Loading @@ -342,6 +378,11 @@ public class GraphicsActivity extends Activity { uniqueFrameRates.add(frameRate); } } Log.i(TAG, "**** Available display refresh rates: " + uniqueFrameRates.stream() .map(Object::toString) .collect(Collectors.joining(", "))); return uniqueFrameRates; } Loading @@ -358,6 +399,10 @@ public class GraphicsActivity extends Activity { <= FRAME_RATE_TOLERANCE; } private boolean frameRateEquals(float frameRate1, float frameRate2) { return Math.abs(frameRate1 - frameRate2) <= FRAME_RATE_TOLERANCE; } // Waits until our SurfaceHolder has a surface and the activity is resumed. private void waitForPreconditions() throws InterruptedException { assertNotSame( Loading Loading @@ -447,9 +492,22 @@ public class GraphicsActivity extends Activity { verifyCompatibleAndStableFrameRate(0, surfaces); } // Set expectedFrameRate to 0.0 to verify only stable frame rate. private void verifyExactAndStableFrameRate( float expectedFrameRate, TestSurface... surfaces) throws InterruptedException { verifyFrameRate(expectedFrameRate, false, surfaces); } private void verifyCompatibleAndStableFrameRate( float expectedFrameRate, TestSurface... surfaces) throws InterruptedException { float expectedFrameRate, TestSurface... surfaces) throws InterruptedException { verifyFrameRate(expectedFrameRate, true, surfaces); } // Set expectedFrameRate to 0.0 to verify only stable frame rate. private void verifyFrameRate( float expectedFrameRate, boolean multiplesAllowed, TestSurface... surfaces) throws InterruptedException { Log.i(TAG, "Verifying compatible and stable frame rate"); long nowNanos = System.nanoTime(); long gracePeriodEndTimeNanos = Loading @@ -457,10 +515,20 @@ public class GraphicsActivity extends Activity { while (true) { if (expectedFrameRate > FRAME_RATE_TOLERANCE) { // expectedFrameRate > 0 // Wait until we switch to a compatible frame rate. Log.i(TAG, "Verifying expected frame rate: actual (device)=" + mDeviceFrameRate + " expected=" + expectedFrameRate); if (multiplesAllowed) { while (!isFrameRateMultiple(mDeviceFrameRate, expectedFrameRate) && !waitForEvents(gracePeriodEndTimeNanos, surfaces)) { // Empty } } else { while (!frameRateEquals(mDeviceFrameRate, expectedFrameRate) && !waitForEvents(gracePeriodEndTimeNanos, surfaces)) { // Empty } } nowNanos = System.nanoTime(); if (nowNanos >= gracePeriodEndTimeNanos) { throw new FrameRateTimeoutException(expectedFrameRate, mDeviceFrameRate); Loading Loading @@ -604,12 +672,65 @@ public class GraphicsActivity extends Activity { "frame rate category=" + category); } private void testSurfaceControlFrameRateSelectionStrategyInternal(int parentStrategy) throws InterruptedException { Log.i(TAG, "**** Running testSurfaceControlFrameRateSelectionStrategy for strategy " + parentStrategy); TestSurface parent = null; TestSurface child = null; try { parent = new TestSurface(mSurfaceView.getSurfaceControl(), mSurface, "testSurfaceParent", mSurfaceView.getHolder().getSurfaceFrame(), /*visible=*/true, Color.RED); child = new TestSurface(parent.getSurfaceControl(), parent.getSurface(), "testSurfaceChild", mSurfaceView.getHolder().getSurfaceFrame(), /*visible=*/true, Color.BLUE); // Test Display display = getDisplay(); List<Float> frameRates = getRefreshRates(display.getMode(), display); assumeTrue("**** SKIPPED due to frame rate override disabled", SurfaceFlingerProperties.enable_frame_rate_override().orElse(true)); float childFrameRate = Collections.max(frameRates); float parentFrameRate = childFrameRate / 2; int initialNumEvents = mModeChangedEvents.size(); parent.setFrameRate(parentFrameRate); parent.setFrameRateSelectionStrategy(parentStrategy); child.setFrameRate(childFrameRate); // Verify float expectedFrameRate = parentStrategy == SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN ? parentFrameRate : childFrameRate; verifyExactAndStableFrameRate(expectedFrameRate, parent, child); verifyModeSwitchesDontChangeResolution(initialNumEvents, mModeChangedEvents.size()); } finally { if (parent != null) { parent.release(); } if (child != null) { child.release(); } } } public void testSurfaceControlFrameRateSelectionStrategy(int parentStrategy) throws InterruptedException { runTestsWithPreconditions( () -> testSurfaceControlFrameRateSelectionStrategyInternal(parentStrategy), "frame rate strategy=" + parentStrategy); } private float getExpectedFrameRate(int category) { Display display = getDisplay(); List<Float> frameRates = getRefreshRates(display.getMode(), display); if (category == Surface.FRAME_RATE_CATEGORY_DEFAULT || category == Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE) { if (category == Surface.FRAME_RATE_CATEGORY_DEFAULT) { // Max due to default vote and no other frame rate specifications. return Collections.max(frameRates); } else if (category == Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE) { return Collections.min(frameRates); } Loading tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/SurfaceControlTest.java +18 −17 Original line number Diff line number Diff line Loading @@ -23,11 +23,14 @@ import android.hardware.display.DisplayManager; import android.os.SystemProperties; import android.support.test.uiautomator.UiDevice; import android.view.Surface; import android.view.SurfaceControl; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; import com.android.compatibility.common.util.DisplayUtil; import org.junit.After; import org.junit.Before; import org.junit.Rule; Loading Loading @@ -59,19 +62,15 @@ public class SurfaceControlTest { uiDevice.executeShellCommand("wm dismiss-keyguard"); InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( Manifest.permission.LOG_COMPAT_CHANGE, Manifest.permission.READ_COMPAT_CHANGE_CONFIG, Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE, Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS, Manifest.permission.MANAGE_GAME_MODE); Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS); // Prevent DisplayManager from limiting the allowed refresh rate range based on // non-app policies (e.g. low battery, user settings, etc). mDisplayManager = activity.getSystemService(DisplayManager.class); mDisplayManager.setShouldAlwaysRespectAppRequestedMode(true); mInitialRefreshRateSwitchingType = toSwitchingType(mDisplayManager.getMatchContentFrameRateUserPreference()); mInitialRefreshRateSwitchingType = DisplayUtil.getRefreshRateSwitchingType(mDisplayManager); mDisplayManager.setRefreshRateSwitchingType( DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS); } Loading Loading @@ -118,16 +117,18 @@ public class SurfaceControlTest { activity.testSurfaceControlFrameRateCategory(Surface.FRAME_RATE_CATEGORY_DEFAULT); } private int toSwitchingType(int matchContentFrameRateUserPreference) { switch (matchContentFrameRateUserPreference) { case DisplayManager.MATCH_CONTENT_FRAMERATE_NEVER: return DisplayManager.SWITCHING_TYPE_NONE; case DisplayManager.MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY: return DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS; case DisplayManager.MATCH_CONTENT_FRAMERATE_ALWAYS: return DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS; default: return -1; @Test public void testSurfaceControlFrameRateSelectionStrategySelf() throws InterruptedException { GraphicsActivity activity = mActivityRule.getActivity(); activity.testSurfaceControlFrameRateSelectionStrategy( SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_SELF); } @Test public void testSurfaceControlFrameRateSelectionStrategyOverrideChildren() throws InterruptedException { GraphicsActivity activity = mActivityRule.getActivity(); activity.testSurfaceControlFrameRateSelectionStrategy( SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN); } } Loading
core/java/android/view/SurfaceControl.java +56 −0 Original line number Diff line number Diff line Loading @@ -263,6 +263,8 @@ public final class SurfaceControl implements Parcelable { long nativeObject, int compatibility); private static native void nativeSetFrameRateCategory( long transactionObj, long nativeObject, int category); private static native void nativeSetFrameRateSelectionStrategy( long transactionObj, long nativeObject, int strategy); private static native long nativeGetHandle(long nativeObject); private static native void nativeSetFixedTransformHint(long transactionObj, long nativeObject, Loading Loading @@ -850,6 +852,35 @@ public final class SurfaceControl implements Parcelable { */ public static final int METADATA_GAME_MODE = 8; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"FRAME_RATE_SELECTION_STRATEGY_"}, value = {FRAME_RATE_SELECTION_STRATEGY_SELF, FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN}) public @interface FrameRateSelectionStrategy {} // From window.h. Keep these in sync. /** * Default value. The layer uses its own frame rate specifications, assuming it has any * specifications, instead of its parent's. * However, {@link #FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN} on an ancestor layer * supersedes this behavior, meaning that this layer will inherit the frame rate specifications * of that ancestor layer. * @hide */ public static final int FRAME_RATE_SELECTION_STRATEGY_SELF = 0; /** * The layer's frame rate specifications will propagate to and override those of its descendant * layers. * The layer with this strategy has the {@link #FRAME_RATE_SELECTION_STRATEGY_SELF} behavior * for itself. This does mean that any parent or ancestor layer that also has the strategy * {@link FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN} will override this layer's * frame rate specifications. * @hide */ public static final int FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN = 1; /** * Builder class for {@link SurfaceControl} objects. * Loading Loading @@ -3668,6 +3699,31 @@ public final class SurfaceControl implements Parcelable { return this; } /** * Sets the frame rate selection strategy for the {@link SurfaceControl}. * * This instructs the system on how to choose a display refresh rate, following the * strategy for the layer's frame rate specifications relative to other layers'. * * @param sc The SurfaceControl to specify the frame rate category of. * @param strategy The frame rate selection strategy. * * @return This transaction object. * * @see #setFrameRate(SurfaceControl, float, int, int) * @see #setFrameRateCategory(SurfaceControl, int) * @see #setDefaultFrameRateCompatibility(SurfaceControl, int) * * @hide */ @NonNull public Transaction setFrameRateSelectionStrategy( @NonNull SurfaceControl sc, @FrameRateSelectionStrategy int strategy) { checkPreconditions(sc); nativeSetFrameRateSelectionStrategy(mNativeObject, sc.mNativeObject, strategy); return this; } /** * Sets focus on the window identified by the input {@code token} if the window is focusable * otherwise the request is dropped. Loading
core/jni/android_view_SurfaceControl.cpp +9 −0 Original line number Diff line number Diff line Loading @@ -967,6 +967,13 @@ static void nativeSetFrameRateCategory(JNIEnv* env, jclass clazz, jlong transact transaction->setFrameRateCategory(ctrl, static_cast<int8_t>(category)); } static void nativeSetFrameRateSelectionStrategy(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jint strategy) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); const auto ctrl = reinterpret_cast<SurfaceControl*>(nativeObject); transaction->setFrameRateSelectionStrategy(ctrl, static_cast<int8_t>(strategy)); } static void nativeSetFixedTransformHint(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jint transformHint) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); Loading Loading @@ -2173,6 +2180,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetDefaultFrameRateCompatibility}, {"nativeSetFrameRateCategory", "(JJI)V", (void*)nativeSetFrameRateCategory}, {"nativeSetFrameRateSelectionStrategy", "(JJI)V", (void*)nativeSetFrameRateSelectionStrategy}, {"nativeSetDisplaySurface", "(JLandroid/os/IBinder;J)V", (void*)nativeSetDisplaySurface }, {"nativeSetDisplayLayerStack", "(JLandroid/os/IBinder;I)V", Loading
tests/CtsSurfaceControlTestsStaging/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ android_test { "androidx.test.rules", "compatibility-device-util-axt", "com.google.android.material_material", "SurfaceFlingerProperties", "truth-prebuilt", ], resource_dirs: ["src/main/res"], Loading
tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/GraphicsActivity.java +128 −7 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.hardware.display.DisplayManager; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.sysprop.SurfaceFlingerProperties; import android.util.Log; import android.view.Display; import android.view.Surface; Loading @@ -45,6 +46,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; /** * An Activity to help with frame rate testing. Loading Loading @@ -217,6 +219,27 @@ public class GraphicsActivity extends Activity { postBuffer(); } Surface getSurface() { return mSurface; } SurfaceControl getSurfaceControl() { return mSurfaceControl; } public int setFrameRate(float frameRate) { Log.i(TAG, String.format("Setting frame rate for %s: frameRate=%.2f", mName, frameRate)); int rc = 0; try (SurfaceControl.Transaction transaction = new SurfaceControl.Transaction()) { transaction.setFrameRate( mSurfaceControl, frameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT); transaction.apply(); } return rc; } public int setFrameRateCategory(int category) { Log.i(TAG, String.format( Loading @@ -230,6 +253,19 @@ public class GraphicsActivity extends Activity { return rc; } public int setFrameRateSelectionStrategy(int strategy) { Log.i(TAG, String.format("Setting frame rate selection strategy for %s: strategy=%d", mName, strategy)); int rc = 0; try (SurfaceControl.Transaction transaction = new SurfaceControl.Transaction()) { transaction.setFrameRateSelectionStrategy(mSurfaceControl, strategy); transaction.apply(); } return rc; } public void setVisibility(boolean visible) { Log.i(TAG, String.format("Setting visibility for %s: %s", mName, Loading Loading @@ -342,6 +378,11 @@ public class GraphicsActivity extends Activity { uniqueFrameRates.add(frameRate); } } Log.i(TAG, "**** Available display refresh rates: " + uniqueFrameRates.stream() .map(Object::toString) .collect(Collectors.joining(", "))); return uniqueFrameRates; } Loading @@ -358,6 +399,10 @@ public class GraphicsActivity extends Activity { <= FRAME_RATE_TOLERANCE; } private boolean frameRateEquals(float frameRate1, float frameRate2) { return Math.abs(frameRate1 - frameRate2) <= FRAME_RATE_TOLERANCE; } // Waits until our SurfaceHolder has a surface and the activity is resumed. private void waitForPreconditions() throws InterruptedException { assertNotSame( Loading Loading @@ -447,9 +492,22 @@ public class GraphicsActivity extends Activity { verifyCompatibleAndStableFrameRate(0, surfaces); } // Set expectedFrameRate to 0.0 to verify only stable frame rate. private void verifyExactAndStableFrameRate( float expectedFrameRate, TestSurface... surfaces) throws InterruptedException { verifyFrameRate(expectedFrameRate, false, surfaces); } private void verifyCompatibleAndStableFrameRate( float expectedFrameRate, TestSurface... surfaces) throws InterruptedException { float expectedFrameRate, TestSurface... surfaces) throws InterruptedException { verifyFrameRate(expectedFrameRate, true, surfaces); } // Set expectedFrameRate to 0.0 to verify only stable frame rate. private void verifyFrameRate( float expectedFrameRate, boolean multiplesAllowed, TestSurface... surfaces) throws InterruptedException { Log.i(TAG, "Verifying compatible and stable frame rate"); long nowNanos = System.nanoTime(); long gracePeriodEndTimeNanos = Loading @@ -457,10 +515,20 @@ public class GraphicsActivity extends Activity { while (true) { if (expectedFrameRate > FRAME_RATE_TOLERANCE) { // expectedFrameRate > 0 // Wait until we switch to a compatible frame rate. Log.i(TAG, "Verifying expected frame rate: actual (device)=" + mDeviceFrameRate + " expected=" + expectedFrameRate); if (multiplesAllowed) { while (!isFrameRateMultiple(mDeviceFrameRate, expectedFrameRate) && !waitForEvents(gracePeriodEndTimeNanos, surfaces)) { // Empty } } else { while (!frameRateEquals(mDeviceFrameRate, expectedFrameRate) && !waitForEvents(gracePeriodEndTimeNanos, surfaces)) { // Empty } } nowNanos = System.nanoTime(); if (nowNanos >= gracePeriodEndTimeNanos) { throw new FrameRateTimeoutException(expectedFrameRate, mDeviceFrameRate); Loading Loading @@ -604,12 +672,65 @@ public class GraphicsActivity extends Activity { "frame rate category=" + category); } private void testSurfaceControlFrameRateSelectionStrategyInternal(int parentStrategy) throws InterruptedException { Log.i(TAG, "**** Running testSurfaceControlFrameRateSelectionStrategy for strategy " + parentStrategy); TestSurface parent = null; TestSurface child = null; try { parent = new TestSurface(mSurfaceView.getSurfaceControl(), mSurface, "testSurfaceParent", mSurfaceView.getHolder().getSurfaceFrame(), /*visible=*/true, Color.RED); child = new TestSurface(parent.getSurfaceControl(), parent.getSurface(), "testSurfaceChild", mSurfaceView.getHolder().getSurfaceFrame(), /*visible=*/true, Color.BLUE); // Test Display display = getDisplay(); List<Float> frameRates = getRefreshRates(display.getMode(), display); assumeTrue("**** SKIPPED due to frame rate override disabled", SurfaceFlingerProperties.enable_frame_rate_override().orElse(true)); float childFrameRate = Collections.max(frameRates); float parentFrameRate = childFrameRate / 2; int initialNumEvents = mModeChangedEvents.size(); parent.setFrameRate(parentFrameRate); parent.setFrameRateSelectionStrategy(parentStrategy); child.setFrameRate(childFrameRate); // Verify float expectedFrameRate = parentStrategy == SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN ? parentFrameRate : childFrameRate; verifyExactAndStableFrameRate(expectedFrameRate, parent, child); verifyModeSwitchesDontChangeResolution(initialNumEvents, mModeChangedEvents.size()); } finally { if (parent != null) { parent.release(); } if (child != null) { child.release(); } } } public void testSurfaceControlFrameRateSelectionStrategy(int parentStrategy) throws InterruptedException { runTestsWithPreconditions( () -> testSurfaceControlFrameRateSelectionStrategyInternal(parentStrategy), "frame rate strategy=" + parentStrategy); } private float getExpectedFrameRate(int category) { Display display = getDisplay(); List<Float> frameRates = getRefreshRates(display.getMode(), display); if (category == Surface.FRAME_RATE_CATEGORY_DEFAULT || category == Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE) { if (category == Surface.FRAME_RATE_CATEGORY_DEFAULT) { // Max due to default vote and no other frame rate specifications. return Collections.max(frameRates); } else if (category == Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE) { return Collections.min(frameRates); } Loading
tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/SurfaceControlTest.java +18 −17 Original line number Diff line number Diff line Loading @@ -23,11 +23,14 @@ import android.hardware.display.DisplayManager; import android.os.SystemProperties; import android.support.test.uiautomator.UiDevice; import android.view.Surface; import android.view.SurfaceControl; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; import com.android.compatibility.common.util.DisplayUtil; import org.junit.After; import org.junit.Before; import org.junit.Rule; Loading Loading @@ -59,19 +62,15 @@ public class SurfaceControlTest { uiDevice.executeShellCommand("wm dismiss-keyguard"); InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( Manifest.permission.LOG_COMPAT_CHANGE, Manifest.permission.READ_COMPAT_CHANGE_CONFIG, Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE, Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS, Manifest.permission.MANAGE_GAME_MODE); Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS); // Prevent DisplayManager from limiting the allowed refresh rate range based on // non-app policies (e.g. low battery, user settings, etc). mDisplayManager = activity.getSystemService(DisplayManager.class); mDisplayManager.setShouldAlwaysRespectAppRequestedMode(true); mInitialRefreshRateSwitchingType = toSwitchingType(mDisplayManager.getMatchContentFrameRateUserPreference()); mInitialRefreshRateSwitchingType = DisplayUtil.getRefreshRateSwitchingType(mDisplayManager); mDisplayManager.setRefreshRateSwitchingType( DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS); } Loading Loading @@ -118,16 +117,18 @@ public class SurfaceControlTest { activity.testSurfaceControlFrameRateCategory(Surface.FRAME_RATE_CATEGORY_DEFAULT); } private int toSwitchingType(int matchContentFrameRateUserPreference) { switch (matchContentFrameRateUserPreference) { case DisplayManager.MATCH_CONTENT_FRAMERATE_NEVER: return DisplayManager.SWITCHING_TYPE_NONE; case DisplayManager.MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY: return DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS; case DisplayManager.MATCH_CONTENT_FRAMERATE_ALWAYS: return DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS; default: return -1; @Test public void testSurfaceControlFrameRateSelectionStrategySelf() throws InterruptedException { GraphicsActivity activity = mActivityRule.getActivity(); activity.testSurfaceControlFrameRateSelectionStrategy( SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_SELF); } @Test public void testSurfaceControlFrameRateSelectionStrategyOverrideChildren() throws InterruptedException { GraphicsActivity activity = mActivityRule.getActivity(); activity.testSurfaceControlFrameRateSelectionStrategy( SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN); } }