Merge "Handle the render frame rate from SF"

This commit is contained in:
Ady Abraham
2022-12-07 02:45:22 +00:00
committed by Android (Google) Code Review
14 changed files with 255 additions and 33 deletions

View File

@@ -227,8 +227,10 @@ public abstract class DisplayEventReceiver {
* timebase.
* @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
* @param modeId The new mode Id
* @param renderPeriod The render frame period, which is a multiple of the mode's vsync period
*/
public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId) {
public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId,
long renderPeriod) {
}
/**
@@ -303,8 +305,9 @@ public abstract class DisplayEventReceiver {
// Called from native code.
@SuppressWarnings("unused")
private void dispatchModeChanged(long timestampNanos, long physicalDisplayId, int modeId) {
onModeChanged(timestampNanos, physicalDisplayId, modeId);
private void dispatchModeChanged(long timestampNanos, long physicalDisplayId, int modeId,
long renderPeriod) {
onModeChanged(timestampNanos, physicalDisplayId, modeId, renderPeriod);
}
// Called from native code.

View File

@@ -179,6 +179,16 @@ public final class DisplayInfo implements Parcelable {
*/
public int modeId;
/**
* The render frame rate this display is scheduled at, which is a divisor of the active mode
* refresh rate. This is the rate SurfaceFlinger would consume frames and would be observable
* by applications via the cadence of {@link android.view.Choreographer} callbacks and
* by backpressure when submitting buffers as fast as possible.
* Apps can call {@link android.view.Display#getRefreshRate} to query this value.
*
*/
public float renderFrameRate;
/**
* The default display mode.
*/
@@ -376,6 +386,7 @@ public final class DisplayInfo implements Parcelable {
&& Objects.equals(displayCutout, other.displayCutout)
&& rotation == other.rotation
&& modeId == other.modeId
&& renderFrameRate == other.renderFrameRate
&& defaultModeId == other.defaultModeId
&& Arrays.equals(supportedModes, other.supportedModes)
&& colorMode == other.colorMode
@@ -428,6 +439,7 @@ public final class DisplayInfo implements Parcelable {
displayCutout = other.displayCutout;
rotation = other.rotation;
modeId = other.modeId;
renderFrameRate = other.renderFrameRate;
defaultModeId = other.defaultModeId;
supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
colorMode = other.colorMode;
@@ -475,6 +487,7 @@ public final class DisplayInfo implements Parcelable {
displayCutout = DisplayCutout.ParcelableWrapper.readCutoutFromParcel(source);
rotation = source.readInt();
modeId = source.readInt();
renderFrameRate = source.readFloat();
defaultModeId = source.readInt();
int nModes = source.readInt();
supportedModes = new Display.Mode[nModes];
@@ -535,6 +548,7 @@ public final class DisplayInfo implements Parcelable {
DisplayCutout.ParcelableWrapper.writeCutoutToParcel(displayCutout, dest, flags);
dest.writeInt(rotation);
dest.writeInt(modeId);
dest.writeFloat(renderFrameRate);
dest.writeInt(defaultModeId);
dest.writeInt(supportedModes.length);
for (int i = 0; i < supportedModes.length; i++) {
@@ -764,6 +778,7 @@ public final class DisplayInfo implements Parcelable {
sb.append(presentationDeadlineNanos);
sb.append(", mode ");
sb.append(modeId);
sb.append(renderFrameRate);
sb.append(", defaultMode ");
sb.append(defaultModeId);
sb.append(", modes ");

View File

@@ -1504,6 +1504,7 @@ public final class SurfaceControl implements Parcelable {
public static final class DynamicDisplayInfo {
public DisplayMode[] supportedDisplayModes;
public int activeDisplayModeId;
public float renderFrameRate;
public int[] supportedColorModes;
public int activeColorMode;
@@ -1520,6 +1521,7 @@ public final class SurfaceControl implements Parcelable {
return "DynamicDisplayInfo{"
+ "supportedDisplayModes=" + Arrays.toString(supportedDisplayModes)
+ ", activeDisplayModeId=" + activeDisplayModeId
+ ", renderFrameRate=" + renderFrameRate
+ ", supportedColorModes=" + Arrays.toString(supportedColorModes)
+ ", activeColorMode=" + activeColorMode
+ ", hdrCapabilities=" + hdrCapabilities
@@ -1535,6 +1537,7 @@ public final class SurfaceControl implements Parcelable {
DynamicDisplayInfo that = (DynamicDisplayInfo) o;
return Arrays.equals(supportedDisplayModes, that.supportedDisplayModes)
&& activeDisplayModeId == that.activeDisplayModeId
&& renderFrameRate == that.renderFrameRate
&& Arrays.equals(supportedColorModes, that.supportedColorModes)
&& activeColorMode == that.activeColorMode
&& Objects.equals(hdrCapabilities, that.hdrCapabilities)
@@ -1544,7 +1547,7 @@ public final class SurfaceControl implements Parcelable {
@Override
public int hashCode() {
return Objects.hash(Arrays.hashCode(supportedDisplayModes), activeDisplayModeId,
activeColorMode, hdrCapabilities);
renderFrameRate, activeColorMode, hdrCapabilities);
}
}

View File

@@ -80,7 +80,7 @@ private:
VsyncEventData vsyncEventData) override;
void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId,
nsecs_t vsyncPeriod) override;
nsecs_t renderPeriod) override;
void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
std::vector<FrameRateOverride> overrides) override;
void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) override {}
@@ -168,14 +168,14 @@ void NativeDisplayEventReceiver::dispatchHotplug(nsecs_t timestamp, PhysicalDisp
}
void NativeDisplayEventReceiver::dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
int32_t modeId, nsecs_t) {
int32_t modeId, nsecs_t renderPeriod) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
if (receiverObj.get()) {
ALOGV("receiver %p ~ Invoking mode changed handler.", this);
env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchModeChanged,
timestamp, displayId.value, modeId);
timestamp, displayId.value, modeId, renderPeriod);
ALOGV("receiver %p ~ Returned from mode changed handler.", this);
}
@@ -290,7 +290,7 @@ int register_android_view_DisplayEventReceiver(JNIEnv* env) {
gDisplayEventReceiverClassInfo.clazz, "dispatchHotplug", "(JJZ)V");
gDisplayEventReceiverClassInfo.dispatchModeChanged =
GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchModeChanged",
"(JJI)V");
"(JJIJ)V");
gDisplayEventReceiverClassInfo.dispatchFrameRateOverrides =
GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz,
"dispatchFrameRateOverrides",

View File

@@ -109,6 +109,7 @@ static struct {
jmethodID ctor;
jfieldID supportedDisplayModes;
jfieldID activeDisplayModeId;
jfieldID renderFrameRate;
jfieldID supportedColorModes;
jfieldID activeColorMode;
jfieldID hdrCapabilities;
@@ -1184,6 +1185,7 @@ static jobject nativeGetDynamicDisplayInfo(JNIEnv* env, jclass clazz, jobject to
env->SetObjectField(object, gDynamicDisplayInfoClassInfo.supportedDisplayModes, modesArray);
env->SetIntField(object, gDynamicDisplayInfoClassInfo.activeDisplayModeId,
info.activeDisplayModeId);
env->SetFloatField(object, gDynamicDisplayInfoClassInfo.renderFrameRate, info.renderFrameRate);
jintArray colorModesArray = env->NewIntArray(info.supportedColorModes.size());
if (colorModesArray == NULL) {
@@ -2174,6 +2176,8 @@ int register_android_view_SurfaceControl(JNIEnv* env)
"[Landroid/view/SurfaceControl$DisplayMode;");
gDynamicDisplayInfoClassInfo.activeDisplayModeId =
GetFieldIDOrDie(env, dynamicInfoClazz, "activeDisplayModeId", "I");
gDynamicDisplayInfoClassInfo.renderFrameRate =
GetFieldIDOrDie(env, dynamicInfoClazz, "renderFrameRate", "F");
gDynamicDisplayInfoClassInfo.supportedColorModes =
GetFieldIDOrDie(env, dynamicInfoClazz, "supportedColorModes", "[I");
gDynamicDisplayInfoClassInfo.activeColorMode =

View File

@@ -244,6 +244,12 @@ final class DisplayDeviceInfo {
*/
public int modeId;
/**
* The render frame rate this display is scheduled at.
* @see android.view.DisplayInfo#renderFrameRate for more details.
*/
public float renderFrameRate;
/**
* The default mode of the display.
*/
@@ -439,6 +445,7 @@ final class DisplayDeviceInfo {
|| width != other.width
|| height != other.height
|| modeId != other.modeId
|| renderFrameRate != other.renderFrameRate
|| defaultModeId != other.defaultModeId
|| !Arrays.equals(supportedModes, other.supportedModes)
|| !Arrays.equals(supportedColorModes, other.supportedColorModes)
@@ -483,6 +490,7 @@ final class DisplayDeviceInfo {
width = other.width;
height = other.height;
modeId = other.modeId;
renderFrameRate = other.renderFrameRate;
defaultModeId = other.defaultModeId;
supportedModes = other.supportedModes;
colorMode = other.colorMode;
@@ -523,6 +531,7 @@ final class DisplayDeviceInfo {
sb.append(name).append("\": uniqueId=\"").append(uniqueId).append("\", ");
sb.append(width).append(" x ").append(height);
sb.append(", modeId ").append(modeId);
sb.append(", renderFrameRate ").append(renderFrameRate);
sb.append(", defaultModeId ").append(defaultModeId);
sb.append(", supportedModes ").append(Arrays.toString(supportedModes));
sb.append(", colorMode ").append(colorMode);

View File

@@ -36,6 +36,7 @@ import static android.hardware.display.DisplayManagerGlobal.DisplayEvent;
import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.ROOT_UID;
import android.Manifest;
@@ -882,20 +883,27 @@ public final class DisplayManagerService extends SystemService {
private DisplayInfo getDisplayInfoForFrameRateOverride(DisplayEventReceiver.FrameRateOverride[]
frameRateOverrides, DisplayInfo info, int callingUid) {
float frameRateHz = 0;
float frameRateHz = info.renderFrameRate;
for (DisplayEventReceiver.FrameRateOverride frameRateOverride : frameRateOverrides) {
if (frameRateOverride.uid == callingUid) {
frameRateHz = frameRateOverride.frameRateHz;
break;
}
}
if (frameRateHz == 0) {
return info;
}
// For non-apps users we always return the physical refresh rate from display mode
boolean displayModeReturnsPhysicalRefreshRate =
callingUid < FIRST_APPLICATION_UID
|| CompatChanges.isChangeEnabled(
DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE, callingUid);
// Override the refresh rate only if it is a divisor of the current
// refresh rate. This calculation needs to be in sync with the native code
// in RefreshRateConfigs::getFrameRateDivisor
// in RefreshRateSelector::getFrameRateDivisor
Display.Mode currentMode = info.getMode();
float numPeriods = currentMode.getRefreshRate() / frameRateHz;
float numPeriodsRound = Math.round(numPeriods);
@@ -919,8 +927,7 @@ public final class DisplayManagerService extends SystemService {
}
overriddenInfo.refreshRateOverride = mode.getRefreshRate();
if (!CompatChanges.isChangeEnabled(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE,
callingUid)) {
if (!displayModeReturnsPhysicalRefreshRate) {
overriddenInfo.modeId = mode.getModeId();
}
return overriddenInfo;
@@ -928,8 +935,7 @@ public final class DisplayManagerService extends SystemService {
}
overriddenInfo.refreshRateOverride = frameRateHz;
if (!CompatChanges.isChangeEnabled(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE,
callingUid)) {
if (!displayModeReturnsPhysicalRefreshRate) {
overriddenInfo.supportedModes = Arrays.copyOf(info.supportedModes,
info.supportedModes.length + 1);
overriddenInfo.supportedModes[overriddenInfo.supportedModes.length - 1] =

View File

@@ -226,6 +226,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
private SurfaceControl.DisplayMode[] mSfDisplayModes;
// The active display mode in SurfaceFlinger
private SurfaceControl.DisplayMode mActiveSfDisplayMode;
// The active display vsync period in SurfaceFlinger
private float mActiveRenderFrameRate;
private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides =
new DisplayEventReceiver.FrameRateOverride[0];
@@ -267,7 +269,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
boolean changed = updateDisplayModesLocked(
dynamicInfo.supportedDisplayModes, dynamicInfo.preferredBootDisplayMode,
dynamicInfo.activeDisplayModeId, modeSpecs);
dynamicInfo.activeDisplayModeId, dynamicInfo.renderFrameRate, modeSpecs);
changed |= updateStaticInfo(staticInfo);
changed |= updateColorModesLocked(dynamicInfo.supportedColorModes,
dynamicInfo.activeColorMode);
@@ -283,7 +285,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
public boolean updateDisplayModesLocked(
SurfaceControl.DisplayMode[] displayModes, int preferredSfDisplayModeId,
int activeSfDisplayModeId, SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
int activeSfDisplayModeId, float renderFrameRate,
SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
mSfDisplayModes = Arrays.copyOf(displayModes, displayModes.length);
mActiveSfDisplayMode = getModeById(displayModes, activeSfDisplayModeId);
SurfaceControl.DisplayMode preferredSfDisplayMode =
@@ -379,6 +382,16 @@ final class LocalDisplayAdapter extends DisplayAdapter {
sendTraversalRequestLocked();
}
boolean renderFrameRateChanged = false;
if (mActiveRenderFrameRate > 0 && mActiveRenderFrameRate != renderFrameRate) {
Slog.d(TAG, "The render frame rate was changed from SurfaceFlinger or the display"
+ " device to " + renderFrameRate);
mActiveRenderFrameRate = renderFrameRate;
renderFrameRateChanged = true;
sendTraversalRequestLocked();
}
// Check whether surface flinger spontaneously changed display config specs out from
// under us. If so, schedule a traversal to reapply our display config specs.
if (mDisplayModeSpecs.baseModeId != INVALID_MODE_ID) {
@@ -398,7 +411,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
boolean recordsChanged = records.size() != mSupportedModes.size() || modesAdded;
// If the records haven't changed then we're done here.
if (!recordsChanged) {
return activeModeChanged || preferredModeChanged;
return activeModeChanged || preferredModeChanged || renderFrameRateChanged;
}
mSupportedModes.clear();
@@ -410,16 +423,19 @@ final class LocalDisplayAdapter extends DisplayAdapter {
if (mDefaultModeId == INVALID_MODE_ID) {
mDefaultModeId = activeRecord.mMode.getModeId();
mDefaultModeGroup = mActiveSfDisplayMode.group;
mActiveRenderFrameRate = renderFrameRate;
} else if (modesAdded && activeModeChanged) {
Slog.d(TAG, "New display modes are added and the active mode has changed, "
+ "use active mode as default mode.");
mDefaultModeId = activeRecord.mMode.getModeId();
mDefaultModeGroup = mActiveSfDisplayMode.group;
mActiveRenderFrameRate = renderFrameRate;
} else if (findSfDisplayModeIdLocked(mDefaultModeId, mDefaultModeGroup) < 0) {
Slog.w(TAG, "Default display mode no longer available, using currently"
+ " active mode as default.");
mDefaultModeId = activeRecord.mMode.getModeId();
mDefaultModeGroup = mActiveSfDisplayMode.group;
mActiveRenderFrameRate = renderFrameRate;
}
// Determine whether the display mode specs' base mode is still there.
@@ -620,6 +636,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mInfo.width = mActiveSfDisplayMode.width;
mInfo.height = mActiveSfDisplayMode.height;
mInfo.modeId = mActiveModeId;
mInfo.renderFrameRate = mActiveRenderFrameRate;
mInfo.defaultModeId = getPreferredModeId();
mInfo.supportedModes = getDisplayModes(mSupportedModes);
mInfo.colorMode = mActiveColorMode;
@@ -995,8 +1012,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
updateDeviceInfoLocked();
}
public void onActiveDisplayModeChangedLocked(int sfModeId) {
if (updateActiveModeLocked(sfModeId)) {
public void onActiveDisplayModeChangedLocked(int sfModeId, float renderFrameRate) {
if (updateActiveModeLocked(sfModeId, renderFrameRate)) {
updateDeviceInfoLocked();
}
}
@@ -1008,8 +1025,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
}
public boolean updateActiveModeLocked(int activeSfModeId) {
if (mActiveSfDisplayMode.id == activeSfModeId) {
public boolean updateActiveModeLocked(int activeSfModeId, float renderFrameRate) {
if (mActiveSfDisplayMode.id == activeSfModeId
&& mActiveRenderFrameRate == renderFrameRate) {
return false;
}
mActiveSfDisplayMode = getModeById(mSfDisplayModes, activeSfModeId);
@@ -1018,6 +1036,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
Slog.w(TAG, "In unknown mode after setting allowed modes"
+ ", activeModeId=" + activeSfModeId);
}
mActiveRenderFrameRate = renderFrameRate;
return true;
}
@@ -1114,6 +1133,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
pw.println(" " + sfDisplayMode);
}
pw.println("mActiveSfDisplayMode=" + mActiveSfDisplayMode);
pw.println("mActiveRenderFrameRate=" + mActiveRenderFrameRate);
pw.println("mSupportedModes=");
for (int i = 0; i < mSupportedModes.size(); i++) {
pw.println(" " + mSupportedModes.valueAt(i));
@@ -1288,7 +1308,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
public interface DisplayEventListener {
void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected);
void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId);
void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId,
long renderPeriod);
void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId,
DisplayEventReceiver.FrameRateOverride[] overrides);
@@ -1309,8 +1330,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
@Override
public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId) {
mListener.onModeChanged(timestampNanos, physicalDisplayId, modeId);
public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId,
long renderPeriod) {
mListener.onModeChanged(timestampNanos, physicalDisplayId, modeId, renderPeriod);
}
@Override
@@ -1333,12 +1355,14 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
@Override
public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId) {
public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId,
long renderPeriod) {
if (DEBUG) {
Slog.d(TAG, "onModeChanged("
+ "timestampNanos=" + timestampNanos
+ ", physicalDisplayId=" + physicalDisplayId
+ ", modeId=" + modeId + ")");
+ ", modeId=" + modeId
+ ", renderPeriod=" + renderPeriod + ")");
}
synchronized (getSyncRoot()) {
LocalDisplayDevice device = mDevices.get(physicalDisplayId);
@@ -1349,7 +1373,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
return;
}
device.onActiveDisplayModeChangedLocked(modeId);
float renderFrameRate = 1e9f / renderPeriod;
device.onActiveDisplayModeChangedLocked(modeId, renderFrameRate);
}
}

View File

@@ -377,6 +377,7 @@ final class LogicalDisplay {
mBaseDisplayInfo.logicalHeight = maskedHeight;
mBaseDisplayInfo.rotation = Surface.ROTATION_0;
mBaseDisplayInfo.modeId = deviceInfo.modeId;
mBaseDisplayInfo.renderFrameRate = deviceInfo.renderFrameRate;
mBaseDisplayInfo.defaultModeId = deviceInfo.defaultModeId;
mBaseDisplayInfo.supportedModes = Arrays.copyOf(
deviceInfo.supportedModes, deviceInfo.supportedModes.length);

View File

@@ -340,6 +340,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
mInfo.width = mode.getPhysicalWidth();
mInfo.height = mode.getPhysicalHeight();
mInfo.modeId = mode.getModeId();
mInfo.renderFrameRate = mode.getRefreshRate();
mInfo.defaultModeId = mModes[0].getModeId();
mInfo.supportedModes = mModes;
mInfo.densityDpi = rawMode.mDensityDpi;

View File

@@ -448,6 +448,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
mInfo.width = mWidth;
mInfo.height = mHeight;
mInfo.modeId = mMode.getModeId();
mInfo.renderFrameRate = mMode.getRefreshRate();
mInfo.defaultModeId = mMode.getModeId();
mInfo.supportedModes = new Display.Mode[] { mMode };
mInfo.densityDpi = mDensityDpi;

View File

@@ -646,6 +646,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
mInfo.width = mWidth;
mInfo.height = mHeight;
mInfo.modeId = mMode.getModeId();
mInfo.renderFrameRate = mMode.getRefreshRate();
mInfo.defaultModeId = mMode.getModeId();
mInfo.supportedModes = new Display.Mode[] { mMode };
mInfo.presentationDeadlineNanos = 1000000000L / (int) mRefreshRate; // 1 frame

View File

@@ -212,7 +212,7 @@ public class LocalDisplayAdapterTest {
SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 0);
displayMode.supportedHdrTypes = new int[0];
FakeDisplay display = new FakeDisplay(PORT_A, new SurfaceControl.DisplayMode[]{displayMode},
0);
0, 0);
setUpDisplay(display);
updateAvailableDisplays();
mAdapter.registerLocked();
@@ -393,7 +393,7 @@ public class LocalDisplayAdapterTest {
SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 60f);
SurfaceControl.DisplayMode[] modes =
new SurfaceControl.DisplayMode[]{displayMode};
FakeDisplay display = new FakeDisplay(PORT_A, modes, 0);
FakeDisplay display = new FakeDisplay(PORT_A, modes, 0, displayMode.refreshRate);
setUpDisplay(display);
updateAvailableDisplays();
mAdapter.registerLocked();
@@ -449,7 +449,7 @@ public class LocalDisplayAdapterTest {
SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 60f);
SurfaceControl.DisplayMode[] modes =
new SurfaceControl.DisplayMode[]{displayMode};
FakeDisplay display = new FakeDisplay(PORT_A, modes, 0);
FakeDisplay display = new FakeDisplay(PORT_A, modes, 0, displayMode.refreshRate);
setUpDisplay(display);
updateAvailableDisplays();
mAdapter.registerLocked();
@@ -504,7 +504,7 @@ public class LocalDisplayAdapterTest {
createFakeDisplayMode(0, 1920, 1080, 60f),
createFakeDisplayMode(1, 1920, 1080, 50f)
};
FakeDisplay display = new FakeDisplay(PORT_A, modes, /* activeMode */ 0);
FakeDisplay display = new FakeDisplay(PORT_A, modes, /* activeMode */ 0, 60f);
setUpDisplay(display);
updateAvailableDisplays();
mAdapter.registerLocked();
@@ -537,6 +537,49 @@ public class LocalDisplayAdapterTest {
assertThat(activeMode.matches(1920, 1080, 50f)).isTrue();
}
@Test
public void testAfterDisplayChange_RenderFrameRateIsUpdated() throws Exception {
SurfaceControl.DisplayMode[] modes = new SurfaceControl.DisplayMode[]{
createFakeDisplayMode(0, 1920, 1080, 60f),
};
FakeDisplay display = new FakeDisplay(PORT_A, modes, /* activeMode */ 0,
/* renderFrameRate */30f);
setUpDisplay(display);
updateAvailableDisplays();
mAdapter.registerLocked();
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
assertThat(mListener.addedDisplays.size()).isEqualTo(1);
assertThat(mListener.changedDisplays).isEmpty();
DisplayDeviceInfo displayDeviceInfo = mListener.addedDisplays.get(0)
.getDisplayDeviceInfoLocked();
Display.Mode activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId);
assertThat(activeMode.matches(1920, 1080, 60f)).isTrue();
assertEquals(Float.floatToIntBits(30f),
Float.floatToIntBits(displayDeviceInfo.renderFrameRate));
// Change the render frame rate
display.dynamicInfo.renderFrameRate = 60f;
setUpDisplay(display);
mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
assertTrue(mListener.traversalRequested);
assertThat(mListener.addedDisplays.size()).isEqualTo(1);
assertThat(mListener.changedDisplays.size()).isEqualTo(1);
DisplayDevice displayDevice = mListener.changedDisplays.get(0);
displayDevice.applyPendingDisplayDeviceInfoChangesLocked();
displayDeviceInfo = displayDevice.getDisplayDeviceInfoLocked();
activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId);
assertThat(activeMode.matches(1920, 1080, 60f)).isTrue();
assertEquals(Float.floatToIntBits(60f),
Float.floatToIntBits(displayDeviceInfo.renderFrameRate));
}
@Test
public void testAfterDisplayChange_HdrCapabilitiesAreUpdated() throws Exception {
FakeDisplay display = new FakeDisplay(PORT_A);
@@ -722,7 +765,7 @@ public class LocalDisplayAdapterTest {
createFakeDisplayMode(1, 1920, 1080, 50f)
};
final int activeMode = 0;
FakeDisplay display = new FakeDisplay(PORT_A, modes, activeMode);
FakeDisplay display = new FakeDisplay(PORT_A, modes, activeMode, 60f);
display.desiredDisplayModeSpecs.defaultMode = 1;
setUpDisplay(display);
@@ -979,11 +1022,13 @@ public class LocalDisplayAdapterTest {
dynamicInfo.activeDisplayModeId = 0;
}
private FakeDisplay(int port, SurfaceControl.DisplayMode[] modes, int activeMode) {
private FakeDisplay(int port, SurfaceControl.DisplayMode[] modes, int activeMode,
float renderFrameRate) {
address = createDisplayAddress(port);
info = createFakeDisplayInfo();
dynamicInfo.supportedDisplayModes = modes;
dynamicInfo.activeDisplayModeId = activeMode;
dynamicInfo.renderFrameRate = renderFrameRate;
}
private FakeDisplay(int port, SurfaceControl.DisplayMode[] modes, int activeMode,

View File

@@ -1252,6 +1252,76 @@ public class DisplayManagerServiceTest {
testDisplayInfoNonNativeFrameRateOverrideMode(/*compatChangeEnabled*/ true);
}
/**
* Tests that there is a display change notification if the render frame rate is updated
*/
@Test
public void testShouldNotifyChangeWhenDisplayInfoRenderFrameRateChanged() throws Exception {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);
DisplayManagerService.BinderService displayManagerBinderService =
displayManager.new BinderService();
registerDefaultDisplays(displayManager);
displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager, new float[]{60f});
FakeDisplayManagerCallback callback = registerDisplayListenerCallback(displayManager,
displayManagerBinderService, displayDevice);
updateRenderFrameRate(displayManager, displayDevice, 30f);
assertTrue(callback.mDisplayChangedCalled);
callback.clear();
updateRenderFrameRate(displayManager, displayDevice, 30f);
assertFalse(callback.mDisplayChangedCalled);
updateRenderFrameRate(displayManager, displayDevice, 20f);
assertTrue(callback.mDisplayChangedCalled);
callback.clear();
}
/**
* Tests that the DisplayInfo is updated correctly with a render frame rate
*/
@Test
public void testDisplayInfoRenderFrameRate() throws Exception {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);
DisplayManagerService.BinderService displayManagerBinderService =
displayManager.new BinderService();
registerDefaultDisplays(displayManager);
displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
new float[]{60f, 30f, 20f});
int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
displayDevice);
DisplayInfo displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
assertEquals(60f, displayInfo.getRefreshRate(), 0.01f);
updateRenderFrameRate(displayManager, displayDevice, 20f);
displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
assertEquals(20f, displayInfo.getRefreshRate(), 0.01f);
}
/**
* Tests that the mode reflects the render frame rate is in compat mode
*/
@Test
@DisableCompatChanges({DisplayManagerService.DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE})
public void testDisplayInfoRenderFrameRateModeCompat() throws Exception {
testDisplayInfoRenderFrameRateModeCompat(/*compatChangeEnabled*/ false);
}
/**
* Tests that the mode reflects the physical display refresh rate when not in compat mode.
*/
@Test
@EnableCompatChanges({DisplayManagerService.DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE})
public void testDisplayInfoRenderFrameRateMode() throws Exception {
testDisplayInfoRenderFrameRateModeCompat(/*compatChangeEnabled*/ true);
}
/**
* Tests that EVENT_DISPLAY_ADDED is sent when a display is added.
*/
@@ -1472,6 +1542,34 @@ public class DisplayManagerServiceTest {
assertEquals(expectedMode, displayInfo.getMode());
}
private void testDisplayInfoRenderFrameRateModeCompat(boolean compatChangeEnabled)
throws Exception {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);
DisplayManagerService.BinderService displayManagerBinderService =
displayManager.new BinderService();
registerDefaultDisplays(displayManager);
displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
new float[]{60f, 30f, 20f});
int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
displayDevice);
DisplayInfo displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
assertEquals(60f, displayInfo.getRefreshRate(), 0.01f);
updateRenderFrameRate(displayManager, displayDevice, 20f);
displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
assertEquals(20f, displayInfo.getRefreshRate(), 0.01f);
Display.Mode expectedMode;
if (compatChangeEnabled) {
expectedMode = new Display.Mode(1, 100, 200, 60f);
} else {
expectedMode = new Display.Mode(3, 100, 200, 20f);
}
assertEquals(expectedMode, displayInfo.getMode());
}
private void testDisplayInfoNonNativeFrameRateOverrideMode(boolean compatChangeEnabled) {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mBasicInjector);
@@ -1541,6 +1639,15 @@ public class DisplayManagerServiceTest {
updateDisplayDeviceInfo(displayManager, displayDevice, displayDeviceInfo);
}
private void updateRenderFrameRate(DisplayManagerService displayManager,
FakeDisplayDevice displayDevice,
float renderFrameRate) {
DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo();
displayDeviceInfo.copyFrom(displayDevice.getDisplayDeviceInfoLocked());
displayDeviceInfo.renderFrameRate = renderFrameRate;
updateDisplayDeviceInfo(displayManager, displayDevice, displayDeviceInfo);
}
private void updateModeId(DisplayManagerService displayManager,
FakeDisplayDevice displayDevice,
int modeId) {
@@ -1580,6 +1687,7 @@ public class DisplayManagerServiceTest {
new Display.Mode(i + 1, width, height, refreshRates[i]);
}
displayDeviceInfo.modeId = 1;
displayDeviceInfo.renderFrameRate = displayDeviceInfo.supportedModes[0].getRefreshRate();
displayDeviceInfo.width = width;
displayDeviceInfo.height = height;
final Rect zeroRect = new Rect();