diff options
10 files changed, 114 insertions, 14 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 614c4c3f37e6..e6c0d45b3e57 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -48751,7 +48751,7 @@ package android.view { method public float getDesiredMaxAverageLuminance(); method public float getDesiredMaxLuminance(); method public float getDesiredMinLuminance(); - method public int[] getSupportedHdrTypes(); + method @Deprecated public int[] getSupportedHdrTypes(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.view.Display.HdrCapabilities> CREATOR; field public static final int HDR_TYPE_DOLBY_VISION = 1; // 0x1 @@ -48768,6 +48768,7 @@ package android.view { method public int getPhysicalHeight(); method public int getPhysicalWidth(); method public float getRefreshRate(); + method @NonNull public int[] getSupportedHdrTypes(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.view.Display.Mode> CREATOR; } diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 274585892b61..a42d3eb9a2d2 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -1942,13 +1942,16 @@ public final class Display { private final float mRefreshRate; @NonNull private final float[] mAlternativeRefreshRates; + @NonNull + @HdrCapabilities.HdrType + private final int[] mSupportedHdrTypes; /** * @hide */ @TestApi public Mode(int width, int height, float refreshRate) { - this(INVALID_MODE_ID, width, height, refreshRate, new float[0]); + this(INVALID_MODE_ID, width, height, refreshRate, new float[0], new int[0]); } /** @@ -1956,14 +1959,14 @@ public final class Display { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Mode(int modeId, int width, int height, float refreshRate) { - this(modeId, width, height, refreshRate, new float[0]); + this(modeId, width, height, refreshRate, new float[0], new int[0]); } /** * @hide */ public Mode(int modeId, int width, int height, float refreshRate, - float[] alternativeRefreshRates) { + float[] alternativeRefreshRates, @HdrCapabilities.HdrType int[] supportedHdrTypes) { mModeId = modeId; mWidth = width; mHeight = height; @@ -1971,6 +1974,8 @@ public final class Display { mAlternativeRefreshRates = Arrays.copyOf(alternativeRefreshRates, alternativeRefreshRates.length); Arrays.sort(mAlternativeRefreshRates); + mSupportedHdrTypes = Arrays.copyOf(supportedHdrTypes, supportedHdrTypes.length); + Arrays.sort(mSupportedHdrTypes); } /** @@ -2045,6 +2050,15 @@ public final class Display { } /** + * Returns the supported {@link HdrCapabilities} HDR_TYPE_* for this specific mode + */ + @NonNull + @HdrCapabilities.HdrType + public int[] getSupportedHdrTypes() { + return mSupportedHdrTypes; + } + + /** * Returns {@code true} if this mode matches the given parameters. * * @hide @@ -2118,7 +2132,8 @@ public final class Display { } Mode that = (Mode) other; return mModeId == that.mModeId && matches(that.mWidth, that.mHeight, that.mRefreshRate) - && Arrays.equals(mAlternativeRefreshRates, that.mAlternativeRefreshRates); + && Arrays.equals(mAlternativeRefreshRates, that.mAlternativeRefreshRates) + && Arrays.equals(mSupportedHdrTypes, that.mSupportedHdrTypes); } @Override @@ -2129,6 +2144,7 @@ public final class Display { hash = hash * 17 + mHeight; hash = hash * 17 + Float.floatToIntBits(mRefreshRate); hash = hash * 17 + Arrays.hashCode(mAlternativeRefreshRates); + hash = hash * 17 + Arrays.hashCode(mSupportedHdrTypes); return hash; } @@ -2141,6 +2157,8 @@ public final class Display { .append(", fps=").append(mRefreshRate) .append(", alternativeRefreshRates=") .append(Arrays.toString(mAlternativeRefreshRates)) + .append(", supportedHdrTypes=") + .append(Arrays.toString(mSupportedHdrTypes)) .append("}") .toString(); } @@ -2151,7 +2169,8 @@ public final class Display { } private Mode(Parcel in) { - this(in.readInt(), in.readInt(), in.readInt(), in.readFloat(), in.createFloatArray()); + this(in.readInt(), in.readInt(), in.readInt(), in.readFloat(), in.createFloatArray(), + in.createIntArray()); } @Override @@ -2161,6 +2180,7 @@ public final class Display { out.writeInt(mHeight); out.writeFloat(mRefreshRate); out.writeFloatArray(mAlternativeRefreshRates); + out.writeIntArray(mSupportedHdrTypes); } @SuppressWarnings("hiding") @@ -2326,6 +2346,9 @@ public final class Display { /** * Gets the supported HDR types of this display. * Returns empty array if HDR is not supported by the display. + * + * @deprecated use {@link Display#getMode()} + * and {@link Mode#getSupportedHdrTypes()} instead */ public @HdrType int[] getSupportedHdrTypes() { return mSupportedHdrTypes; diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index e1ca0f139113..30e7a7ac5a45 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -1563,6 +1563,7 @@ public final class SurfaceControl implements Parcelable { public float refreshRate; public long appVsyncOffsetNanos; public long presentationDeadlineNanos; + public int[] supportedHdrTypes; /** * The config group ID this config is associated to. @@ -1582,6 +1583,7 @@ public final class SurfaceControl implements Parcelable { + ", refreshRate=" + refreshRate + ", appVsyncOffsetNanos=" + appVsyncOffsetNanos + ", presentationDeadlineNanos=" + presentationDeadlineNanos + + ", supportedHdrTypes=" + Arrays.toString(supportedHdrTypes) + ", group=" + group + "}"; } @@ -1598,13 +1600,14 @@ public final class SurfaceControl implements Parcelable { && Float.compare(that.refreshRate, refreshRate) == 0 && appVsyncOffsetNanos == that.appVsyncOffsetNanos && presentationDeadlineNanos == that.presentationDeadlineNanos + && Arrays.equals(supportedHdrTypes, that.supportedHdrTypes) && group == that.group; } @Override public int hashCode() { return Objects.hash(id, width, height, xDpi, yDpi, refreshRate, appVsyncOffsetNanos, - presentationDeadlineNanos, group); + presentationDeadlineNanos, group, Arrays.hashCode(supportedHdrTypes)); } } diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 5a0a84b9a4ba..2c5386d6da69 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -129,6 +129,7 @@ static struct { jfieldID appVsyncOffsetNanos; jfieldID presentationDeadlineNanos; jfieldID group; + jfieldID supportedHdrTypes; } gDisplayModeClassInfo; // Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref. @@ -1130,6 +1131,16 @@ static jobject convertDisplayModeToJavaObject(JNIEnv* env, const ui::DisplayMode env->SetLongField(object, gDisplayModeClassInfo.presentationDeadlineNanos, config.presentationDeadline); env->SetIntField(object, gDisplayModeClassInfo.group, config.group); + + const auto& types = config.supportedHdrTypes; + std::vector<jint> intTypes; + for (auto type : types) { + intTypes.push_back(static_cast<jint>(type)); + } + auto typesArray = env->NewIntArray(types.size()); + env->SetIntArrayRegion(typesArray, 0, intTypes.size(), intTypes.data()); + env->SetObjectField(object, gDisplayModeClassInfo.supportedHdrTypes, typesArray); + return object; } @@ -2191,6 +2202,8 @@ int register_android_view_SurfaceControl(JNIEnv* env) gDisplayModeClassInfo.presentationDeadlineNanos = GetFieldIDOrDie(env, modeClazz, "presentationDeadlineNanos", "J"); gDisplayModeClassInfo.group = GetFieldIDOrDie(env, modeClazz, "group", "I"); + gDisplayModeClassInfo.supportedHdrTypes = + GetFieldIDOrDie(env, modeClazz, "supportedHdrTypes", "[I"); jclass frameStatsClazz = FindClassOrDie(env, "android/view/FrameStats"); jfieldID undefined_time_nano_field = GetStaticFieldIDOrDie(env, diff --git a/core/tests/mockingcoretests/src/android/view/DisplayTest.java b/core/tests/mockingcoretests/src/android/view/DisplayTest.java index 0c939ec24643..9ccf3b3c9d05 100644 --- a/core/tests/mockingcoretests/src/android/view/DisplayTest.java +++ b/core/tests/mockingcoretests/src/android/view/DisplayTest.java @@ -27,6 +27,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSess import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertArrayEquals; + import android.app.WindowConfiguration; import android.content.Context; import android.content.res.Resources; @@ -399,6 +401,15 @@ public class DisplayTest { verifyRealMetricsMatchesBounds(display, sDeviceBoundsLandscape); } + @Test + public void testSupportedHdrTypesForDisplayModeAreSorted() { + int[] nonSortedHdrTypes = new int[]{3, 2, 1}; + Display.Mode displayMode = new Display.Mode(0, 0, 0, 0, new float[0], nonSortedHdrTypes); + + int[] sortedHdrTypes = new int[]{1, 2, 3}; + assertArrayEquals(sortedHdrTypes, displayMode.getSupportedHdrTypes()); + } + // Given rotated display dimensions, calculate the letterboxed app bounds. private static Rect buildAppBounds(int displayWidth, int displayHeight) { final int midWidth = displayWidth / 2; diff --git a/services/core/java/com/android/server/display/DisplayAdapter.java b/services/core/java/com/android/server/display/DisplayAdapter.java index 1fc151221b46..4f1df3fb996e 100644 --- a/services/core/java/com/android/server/display/DisplayAdapter.java +++ b/services/core/java/com/android/server/display/DisplayAdapter.java @@ -120,13 +120,14 @@ abstract class DisplayAdapter { } public static Display.Mode createMode(int width, int height, float refreshRate) { - return createMode(width, height, refreshRate, new float[0]); + return createMode(width, height, refreshRate, new float[0], new int[0]); } public static Display.Mode createMode(int width, int height, float refreshRate, - float[] alternativeRefreshRates) { + float[] alternativeRefreshRates, + @Display.HdrCapabilities.HdrType int[] supportedHdrTypes) { return new Display.Mode(NEXT_DISPLAY_MODE_ID.getAndIncrement(), width, height, refreshRate, - alternativeRefreshRates); + alternativeRefreshRates, supportedHdrTypes); } public interface Listener { diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 1d04f2ef99c0..a7e6b7fdb862 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -934,7 +934,8 @@ public final class DisplayManagerService extends SystemService { overriddenInfo.supportedModes[overriddenInfo.supportedModes.length - 1] = new Display.Mode(Display.DISPLAY_MODE_ID_FOR_FRAME_RATE_OVERRIDE, currentMode.getPhysicalWidth(), currentMode.getPhysicalHeight(), - overriddenInfo.refreshRateOverride); + overriddenInfo.refreshRateOverride, + new float[0], currentMode.getSupportedHdrTypes()); overriddenInfo.modeId = overriddenInfo.supportedModes[overriddenInfo.supportedModes.length - 1] .getModeId(); diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index f85b99082d54..dc5c80f20d78 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -584,7 +584,9 @@ final class LocalDisplayAdapter extends DisplayAdapter { DisplayModeRecord record = mSupportedModes.valueAt(i); if (record.hasMatchingMode(mode) && refreshRatesEquals(alternativeRefreshRates, - record.mMode.getAlternativeRefreshRates())) { + record.mMode.getAlternativeRefreshRates()) + && hdrTypesEqual(mode.supportedHdrTypes, + record.mMode.getSupportedHdrTypes())) { return record; } } @@ -1226,6 +1228,13 @@ final class LocalDisplayAdapter extends DisplayAdapter { } } + private boolean hdrTypesEqual(int[] modeHdrTypes, int[] recordHdrTypes) { + int[] modeHdrTypesCopy = Arrays.copyOf(modeHdrTypes, modeHdrTypes.length); + Arrays.sort(modeHdrTypesCopy); + // Record HDR types are already sorted when we create the DisplayModeRecord + return Arrays.equals(modeHdrTypesCopy, recordHdrTypes); + } + /** Supplies a context whose Resources apply runtime-overlays */ Context getOverlayContext() { if (mOverlayContext == null) { @@ -1243,7 +1252,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { DisplayModeRecord(SurfaceControl.DisplayMode mode, float[] alternativeRefreshRates) { mMode = createMode(mode.width, mode.height, mode.refreshRate, - alternativeRefreshRates); + alternativeRefreshRates, mode.supportedHdrTypes); } /** @@ -1257,7 +1266,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { return mMode.getPhysicalWidth() == mode.width && mMode.getPhysicalHeight() == mode.height && Float.floatToIntBits(mMode.getRefreshRate()) - == Float.floatToIntBits(mode.refreshRate); + == Float.floatToIntBits(mode.refreshRate); } public String toString() { diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java index 395e6ac1017d..be32b79a9d13 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -23,6 +23,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -58,6 +59,7 @@ import com.android.server.lights.LogicalLight; import com.google.common.truth.Truth; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -84,6 +86,8 @@ public class LocalDisplayAdapterTest { private static final long HANDLER_WAIT_MS = 100; + private static final int[] HDR_TYPES = new int[]{1, 2}; + private StaticMockitoSession mMockitoSession; private LocalDisplayAdapter mAdapter; @@ -202,6 +206,38 @@ public class LocalDisplayAdapterTest { PORT_C, false); } + @Test + public void testSupportedDisplayModesGetOverriddenWhenDisplayIsUpdated() + throws InterruptedException { + SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 0); + displayMode.supportedHdrTypes = new int[0]; + FakeDisplay display = new FakeDisplay(PORT_A, new SurfaceControl.DisplayMode[]{displayMode}, + 0); + setUpDisplay(display); + updateAvailableDisplays(); + mAdapter.registerLocked(); + waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); + + DisplayDevice displayDevice = mListener.addedDisplays.get(0); + displayDevice.applyPendingDisplayDeviceInfoChangesLocked(); + Display.Mode[] supportedModes = displayDevice.getDisplayDeviceInfoLocked().supportedModes; + Assert.assertEquals(1, supportedModes.length); + Assert.assertEquals(0, supportedModes[0].getSupportedHdrTypes().length); + + displayMode.supportedHdrTypes = new int[]{3, 2}; + display.dynamicInfo.supportedDisplayModes = new SurfaceControl.DisplayMode[]{displayMode}; + setUpDisplay(display); + mInjector.getTransmitter().sendHotplug(display, true); + waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); + + displayDevice = mListener.changedDisplays.get(0); + displayDevice.applyPendingDisplayDeviceInfoChangesLocked(); + supportedModes = displayDevice.getDisplayDeviceInfoLocked().supportedModes; + + Assert.assertEquals(1, supportedModes.length); + assertArrayEquals(new int[]{2, 3}, supportedModes[0].getSupportedHdrTypes()); + } + /** * Confirm that all local displays are public when config_localPrivateDisplayPorts is empty. */ @@ -1008,6 +1044,7 @@ public class LocalDisplayAdapterTest { mode.xDpi = 100; mode.yDpi = 100; mode.group = group; + mode.supportedHdrTypes = HDR_TYPES; return mode; } diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java index 109abd03747c..5af05584c07a 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -219,6 +219,7 @@ public class DisplayManagerServiceTest { SurfaceControl.DisplayMode displayMode = new SurfaceControl.DisplayMode(); displayMode.width = 100; displayMode.height = 200; + displayMode.supportedHdrTypes = new int[]{1, 2}; dynamicDisplayMode.supportedDisplayModes = new SurfaceControl.DisplayMode[] {displayMode}; when(mSurfaceControlProxy.getDynamicDisplayInfo(mMockDisplayToken)) .thenReturn(dynamicDisplayMode); |