From 6af2931a50509fec59fa254d42fe9ca19d1994ae Mon Sep 17 00:00:00 2001 From: Kriti Dang Date: Thu, 1 Dec 2022 16:34:27 +0100 Subject: [PATCH] APIs for HDR output control New APIs are added to DisplayManager to set/get HDR conversion properties. The setter is protected by a new permission. Bug: 251168516 Test: atest HdrConversionTest Change-Id: I644ee747b669612f78413117e4f8617dccf88f41 --- core/api/current.txt | 1 + core/api/test-current.txt | 17 +++ .../hardware/display/DisplayManager.java | 48 +++++++ .../display/DisplayManagerGlobal.java | 33 +++++ .../hardware/display/HdrConversionMode.aidl | 19 +++ .../hardware/display/HdrConversionMode.java | 122 ++++++++++++++++++ .../hardware/display/IDisplayManager.aidl | 9 ++ core/java/android/view/Display.java | 5 + core/res/AndroidManifest.xml | 6 + packages/Shell/AndroidManifest.xml | 3 + .../server/display/DisplayControl.java | 20 +++ .../server/display/DisplayManagerService.java | 97 +++++++++++++- ..._android_server_display_DisplayControl.cpp | 57 ++++++++ 13 files changed, 435 insertions(+), 2 deletions(-) create mode 100644 core/java/android/hardware/display/HdrConversionMode.aidl create mode 100644 core/java/android/hardware/display/HdrConversionMode.java diff --git a/core/api/current.txt b/core/api/current.txt index f50d3ca98960a..65a89fe58f6a4 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -49502,6 +49502,7 @@ package android.view { field public static final int HDR_TYPE_HDR10 = 2; // 0x2 field public static final int HDR_TYPE_HDR10_PLUS = 4; // 0x4 field public static final int HDR_TYPE_HLG = 3; // 0x3 + field public static final int HDR_TYPE_INVALID = -1; // 0xffffffff field public static final float INVALID_LUMINANCE = -1.0f; } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 8c64e4046013c..a48a1034ef14a 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -29,6 +29,7 @@ package android { field public static final String MANAGE_NOTIFICATION_LISTENERS = "android.permission.MANAGE_NOTIFICATION_LISTENERS"; field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS"; field public static final String MANAGE_TOAST_RATE_LIMITING = "android.permission.MANAGE_TOAST_RATE_LIMITING"; + field public static final String MODIFY_HDR_CONVERSION_MODE = "android.permission.MODIFY_HDR_CONVERSION_MODE"; field public static final String MODIFY_REFRESH_RATE_SWITCHING_TYPE = "android.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE"; field public static final String MODIFY_USER_PREFERRED_DISPLAY_MODE = "android.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE"; field public static final String NETWORK_SETTINGS = "android.permission.NETWORK_SETTINGS"; @@ -1332,11 +1333,14 @@ package android.hardware.display { method public boolean areUserDisabledHdrTypesAllowed(); method @RequiresPermission(android.Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE) public void clearGlobalUserPreferredDisplayMode(); method @Nullable public android.view.Display.Mode getGlobalUserPreferredDisplayMode(); + method @NonNull public android.hardware.display.HdrConversionMode getHdrConversionMode(); + method @NonNull public int[] getSupportedHdrOutputTypes(); method @NonNull public int[] getUserDisabledHdrTypes(); method public boolean isMinimalPostProcessingRequested(int); method @RequiresPermission(android.Manifest.permission.ACCESS_SURFACE_FLINGER) public void overrideHdrTypes(int, @NonNull int[]); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAreUserDisabledHdrTypesAllowed(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE) public void setGlobalUserPreferredDisplayMode(@NonNull android.view.Display.Mode); + method @RequiresPermission(android.Manifest.permission.MODIFY_HDR_CONVERSION_MODE) public void setHdrConversionMode(@NonNull android.hardware.display.HdrConversionMode); method @RequiresPermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE) public void setRefreshRateSwitchingType(int); method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public void setShouldAlwaysRespectAppRequestedMode(boolean); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setUserDisabledHdrTypes(@NonNull int[]); @@ -1349,6 +1353,19 @@ package android.hardware.display { field public static final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 512; // 0x200 } + public final class HdrConversionMode implements android.os.Parcelable { + ctor public HdrConversionMode(int, int); + ctor public HdrConversionMode(int); + method public int describeContents(); + method public int getConversionMode(); + method public int getPreferredHdrOutputType(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int HDR_CONVERSION_FORCE = 3; // 0x3 + field public static final int HDR_CONVERSION_PASSTHROUGH = 1; // 0x1 + field public static final int HDR_CONVERSION_SYSTEM = 2; // 0x2 + } + } package android.hardware.fingerprint { diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index b333f5acd7939..08238ca4365e2 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -1300,6 +1300,54 @@ public final class DisplayManager { return mGlobal.getUserPreferredDisplayMode(Display.INVALID_DISPLAY); } + /** + * Sets the HDR conversion mode for the device. + * + * @param hdrConversionMode The {@link HdrConversionMode} to set. + * Note, {@code HdrConversionMode.preferredHdrOutputType} is only applicable when + * {@code HdrConversionMode.conversionMode} is {@link HdrConversionMode#HDR_CONVERSION_FORCE}. + * + * @throws IllegalArgumentException if hdrConversionMode.preferredHdrOutputType is not set + * when hdrConversionMode.conversionMode is {@link HdrConversionMode#HDR_CONVERSION_FORCE}. + * @throws IllegalArgumentException if hdrConversionMode.preferredHdrOutputType is set but + * hdrConversionMode.conversionMode is not {@link HdrConversionMode#HDR_CONVERSION_FORCE}. + * + * @see #getHdrConversionMode + * @see #getSupportedHdrOutputTypes + * @hide + */ + @TestApi + @RequiresPermission(Manifest.permission.MODIFY_HDR_CONVERSION_MODE) + public void setHdrConversionMode(@NonNull HdrConversionMode hdrConversionMode) { + mGlobal.setHdrConversionMode(hdrConversionMode); + } + + /** + * Returns the {@link HdrConversionMode} of the device, which is set by the user. + * + * @see #setHdrConversionMode + * @see #getSupportedHdrOutputTypes + * @hide + */ + @TestApi + @NonNull + public HdrConversionMode getHdrConversionMode() { + return mGlobal.getHdrConversionMode(); + } + + /** + * Returns the HDR output types supported by the device. + * + * @see #getHdrConversionMode + * @see #setHdrConversionMode + * @hide + */ + @TestApi + @NonNull + public @HdrType int[] getSupportedHdrOutputTypes() { + return mGlobal.getSupportedHdrOutputTypes(); + } + /** * When enabled the app requested mode is always selected regardless of user settings and * policies for low brightness, low battery, etc. diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index f038c66d3b51a..d9db177b4c18f 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -978,6 +978,39 @@ public final class DisplayManagerGlobal { } } + /** + * Sets the {@link HdrConversionMode} for the device. + */ + public void setHdrConversionMode(@NonNull HdrConversionMode hdrConversionMode) { + try { + mDm.setHdrConversionMode(hdrConversionMode); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /** + * Returns the {@link HdrConversionMode} of the device. + */ + public HdrConversionMode getHdrConversionMode() { + try { + return mDm.getHdrConversionMode(); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /** + * Returns the HDR output types supported by the device. + */ + public @HdrType int[] getSupportedHdrOutputTypes() { + try { + return mDm.getSupportedHdrOutputTypes(); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + /** * When enabled the app requested display resolution and refresh rate is always selected * in DisplayModeDirector regardless of user settings and policies for low brightness, low diff --git a/core/java/android/hardware/display/HdrConversionMode.aidl b/core/java/android/hardware/display/HdrConversionMode.aidl new file mode 100644 index 0000000000000..ac89dd6ef2bc3 --- /dev/null +++ b/core/java/android/hardware/display/HdrConversionMode.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.display; + +parcelable HdrConversionMode; \ No newline at end of file diff --git a/core/java/android/hardware/display/HdrConversionMode.java b/core/java/android/hardware/display/HdrConversionMode.java new file mode 100644 index 0000000000000..1accd17482861 --- /dev/null +++ b/core/java/android/hardware/display/HdrConversionMode.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.display; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.TestApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.view.Display; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Describes the HDR conversion mode for a device. + * + * This class is used when user changes the HDR conversion mode of the device via + * {@link DisplayManager#setHdrConversionMode(HdrConversionMode)}. + *

+ * HDR conversion mode has a conversionMode and preferredHdrOutputType.

+ * The conversionMode can be one of: + * HDR_CONVERSION_PASSSTHROUGH : HDR conversion is disabled. The output HDR type will change + * dynamically to match the content. In this mode, preferredHdrOutputType should not be set. + * HDR_CONVERSION_AUTO: The output HDR type is selected by the implementation. In this mode, + * preferredHdrOutputType should not be set. + * HDR_CONVERSION_FORCE : The implementation converts all content to this HDR type, when possible. + * In this mode, preferredHdrOutputType should be set. + *

+ * @hide + */ +@TestApi +public final class HdrConversionMode implements Parcelable { + /** HDR output conversion is disabled */ + public static final int HDR_CONVERSION_PASSTHROUGH = 1; + /** HDR output conversion is managed by the device manufacturer's implementation. */ + public static final int HDR_CONVERSION_SYSTEM = 2; + /** + * HDR output conversion is set by the user. The preferred output type must be + * set in this case. + */ + public static final int HDR_CONVERSION_FORCE = 3; + + /** @hide */ + @IntDef(prefix = {"HDR_CONVERSION"}, value = { + HDR_CONVERSION_PASSTHROUGH, + HDR_CONVERSION_SYSTEM, + HDR_CONVERSION_FORCE + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ConversionMode {} + + public static final @NonNull + Parcelable.Creator CREATOR = + new Parcelable.Creator<>() { + @Override + public HdrConversionMode createFromParcel(Parcel source) { + return new HdrConversionMode(source); + } + + @Override + public HdrConversionMode[] newArray(int size) { + return new HdrConversionMode[size]; + } + }; + + private final @ConversionMode int mConversionMode; + private @Display.HdrCapabilities.HdrType int mPreferredHdrOutputType; + + public HdrConversionMode(int conversionMode, int preferredHdrOutputType) { + if (conversionMode != HdrConversionMode.HDR_CONVERSION_FORCE + && preferredHdrOutputType != -1) { + throw new IllegalArgumentException("preferredHdrOutputType must not be set if" + + " the conversion mode is not HDR_CONVERSION_FORCE"); + } + + mConversionMode = conversionMode; + mPreferredHdrOutputType = preferredHdrOutputType; + } + + public HdrConversionMode(int conversionMode) { + mConversionMode = conversionMode; + mPreferredHdrOutputType = Display.HdrCapabilities.HDR_TYPE_INVALID; + } + + private HdrConversionMode(Parcel source) { + this(source.readInt(), source.readInt()); + } + + public int getConversionMode() { + return mConversionMode; + } + + public int getPreferredHdrOutputType() { + return mPreferredHdrOutputType; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mConversionMode); + dest.writeInt(mPreferredHdrOutputType); + } +} diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index 28bb35f7d9cf4..0a44f8509c765 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -23,6 +23,7 @@ import android.hardware.display.BrightnessConfiguration; import android.hardware.display.BrightnessInfo; import android.hardware.display.Curve; import android.hardware.graphics.common.DisplayDecorationSupport; +import android.hardware.display.HdrConversionMode; import android.hardware.display.IDisplayManagerCallback; import android.hardware.display.IVirtualDisplayCallback; import android.hardware.display.VirtualDisplayConfig; @@ -174,6 +175,14 @@ interface IDisplayManager { Mode getUserPreferredDisplayMode(int displayId); Mode getSystemPreferredDisplayMode(int displayId); + // Sets the HDR conversion mode for a device. + // Requires MODIFY_HDR_CONVERSION_MODE permission. + @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest" + + ".permission.MODIFY_HDR_CONVERSION_MODE)") + void setHdrConversionMode(in HdrConversionMode hdrConversionMode); + HdrConversionMode getHdrConversionMode(); + int[] getSupportedHdrOutputTypes(); + // When enabled the app requested display resolution and refresh rate is always selected // in DisplayModeDirector regardless of user settings and policies for low brightness, low // battery etc. diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 689dce8f14f78..25863a6babe13 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -2322,6 +2322,10 @@ public final class Display { * Invalid luminance value. */ public static final float INVALID_LUMINANCE = -1; + /** + * Invalid HDR type value. + */ + public static final int HDR_TYPE_INVALID = -1; /** * Dolby Vision high dynamic range (HDR) display. */ @@ -2350,6 +2354,7 @@ public final class Display { /** @hide */ @IntDef(prefix = { "HDR_TYPE_" }, value = { + HDR_TYPE_INVALID, HDR_TYPE_DOLBY_VISION, HDR_TYPE_HDR10, HDR_TYPE_HLG, diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index bc40cefe6510f..640b84a3580b1 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -5244,6 +5244,12 @@ + + + diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index c641a8535c3c2..43062d44acfb2 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -508,6 +508,9 @@ + + + diff --git a/services/core/java/com/android/server/display/DisplayControl.java b/services/core/java/com/android/server/display/DisplayControl.java index 864510ea96b93..fa9a100afd048 100644 --- a/services/core/java/com/android/server/display/DisplayControl.java +++ b/services/core/java/com/android/server/display/DisplayControl.java @@ -20,6 +20,7 @@ import android.Manifest; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.os.IBinder; +import android.view.Display; import java.util.Objects; @@ -32,6 +33,9 @@ public class DisplayControl { private static native void nativeOverrideHdrTypes(IBinder displayToken, int[] modes); private static native long[] nativeGetPhysicalDisplayIds(); private static native IBinder nativeGetPhysicalDisplayToken(long physicalDisplayId); + private static native void nativeSetHdrConversionMode(int conversionMode, + int preferredHdrOutputType, int[] autoHdrTypes, int autoHdrTypesLength); + private static native int[] nativeGetSupportedHdrOutputTypes(); /** * Create a display in SurfaceFlinger. @@ -79,4 +83,20 @@ public class DisplayControl { public static IBinder getPhysicalDisplayToken(long physicalDisplayId) { return nativeGetPhysicalDisplayToken(physicalDisplayId); } + + /** + * @hide + */ + public static void setHdrConversionMode(int conversionMode, int preferredHdrOutputType, + int[] autoHdrTypes) { + int length = autoHdrTypes != null ? autoHdrTypes.length : 0; + nativeSetHdrConversionMode(conversionMode, preferredHdrOutputType, autoHdrTypes, length); + } + + /** + * @hide + */ + public static @Display.HdrCapabilities.HdrType int[] getSupportedHdrOutputTypes() { + return nativeGetSupportedHdrOutputTypes(); + } } diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 06b99f82362ad..9ac3c553d6792 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -79,6 +79,7 @@ import android.hardware.display.DisplayManagerInternal.DisplayTransactionListene import android.hardware.display.DisplayViewport; import android.hardware.display.DisplayedContentSample; import android.hardware.display.DisplayedContentSamplingAttributes; +import android.hardware.display.HdrConversionMode; import android.hardware.display.IDisplayManager; import android.hardware.display.IDisplayManagerCallback; import android.hardware.display.IVirtualDisplayCallback; @@ -233,11 +234,17 @@ public final class DisplayManagerService extends SystemService { private InputManagerInternal mInputManagerInternal; private IMediaProjectionManager mProjectionService; private DeviceStateManagerInternal mDeviceStateManager; + @GuardedBy("mSyncRoot") private int[] mUserDisabledHdrTypes = {}; + private int[] mSupportedHdrOutputType; + @GuardedBy("mSyncRoot") private boolean mAreUserDisabledHdrTypesAllowed = true; // Display mode chosen by user. private Display.Mode mUserPreferredMode; + // HDR conversion mode chosen by user + @GuardedBy("mSyncRoot") + private HdrConversionMode mHdrConversionMode; // The synchronization root for the display manager. // This lock guards most of the display manager's state. @@ -880,8 +887,8 @@ public final class DisplayManagerService extends SystemService { } private void clearUserDisabledHdrTypesLocked() { - mUserDisabledHdrTypes = new int[]{}; synchronized (mSyncRoot) { + mUserDisabledHdrTypes = new int[]{}; Settings.Global.putString(mContext.getContentResolver(), Settings.Global.USER_DISABLED_HDR_FORMATS, ""); } @@ -1904,6 +1911,24 @@ public final class DisplayManagerService extends SystemService { }); } + @GuardedBy("mSyncRoot") + private int[] getEnabledAutoHdrTypesLocked() { + IntArray autoHdrOutputTypesArray = new IntArray(); + for (int type : getSupportedHdrOutputTypesInternal()) { + boolean isDisabled = false; + for (int disabledType : mUserDisabledHdrTypes) { + if (type == disabledType) { + isDisabled = true; + break; + } + } + if (!isDisabled) { + autoHdrOutputTypesArray.add(type); + } + } + return autoHdrOutputTypesArray.toArray(); + } + Display.Mode getUserPreferredDisplayModeInternal(int displayId) { synchronized (mSyncRoot) { if (displayId == Display.INVALID_DISPLAY) { @@ -1927,6 +1952,38 @@ public final class DisplayManagerService extends SystemService { } } + // TODO (b/264979880) - Add unit test for HDR output control methods. + private void setHdrConversionModeInternal(HdrConversionMode hdrConversionMode) { + int[] autoHdrOutputTypes = null; + synchronized (mSyncRoot) { + mHdrConversionMode = hdrConversionMode; + + // For auto mode, all supported HDR types are allowed except the ones specifically + // disabled by the user. + if (hdrConversionMode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM) { + autoHdrOutputTypes = getEnabledAutoHdrTypesLocked(); + } + DisplayControl.setHdrConversionMode(hdrConversionMode.getConversionMode(), + hdrConversionMode.getPreferredHdrOutputType(), autoHdrOutputTypes); + } + } + + private HdrConversionMode getHdrConversionModeInternal() { + synchronized (mSyncRoot) { + if (mHdrConversionMode != null) { + return mHdrConversionMode; + } + } + return new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM); + } + + private @Display.HdrCapabilities.HdrType int[] getSupportedHdrOutputTypesInternal() { + if (mSupportedHdrOutputType == null) { + mSupportedHdrOutputType = DisplayControl.getSupportedHdrOutputTypes(); + } + return mSupportedHdrOutputType; + } + void setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled) { mDisplayModeDirector.setShouldAlwaysRespectAppRequestedMode(enabled); } @@ -3193,7 +3250,9 @@ public final class DisplayManagerService extends SystemService { @Override // Binder call public int[] getUserDisabledHdrTypes() { - return mUserDisabledHdrTypes; + synchronized (mSyncRoot) { + return mUserDisabledHdrTypes; + } } @Override // Binder call @@ -3611,6 +3670,40 @@ public final class DisplayManagerService extends SystemService { } } + @Override // Binder call + public void setHdrConversionMode(HdrConversionMode hdrConversionMode) { + mContext.enforceCallingOrSelfPermission( + Manifest.permission.MODIFY_HDR_CONVERSION_MODE, + "Permission required to set the HDR conversion mode."); + final long token = Binder.clearCallingIdentity(); + try { + setHdrConversionModeInternal(hdrConversionMode); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override // Binder call + public HdrConversionMode getHdrConversionMode() { + final long token = Binder.clearCallingIdentity(); + try { + return getHdrConversionModeInternal(); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Display.HdrCapabilities.HdrType + @Override // Binder call + public int[] getSupportedHdrOutputTypes() { + final long token = Binder.clearCallingIdentity(); + try { + return getSupportedHdrOutputTypesInternal(); + } finally { + Binder.restoreCallingIdentity(token); + } + } + @Override // Binder call public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) { mContext.enforceCallingOrSelfPermission( diff --git a/services/core/jni/com_android_server_display_DisplayControl.cpp b/services/core/jni/com_android_server_display_DisplayControl.cpp index 185933382384e..ec423241918af 100644 --- a/services/core/jni/com_android_server_display_DisplayControl.cpp +++ b/services/core/jni/com_android_server_display_DisplayControl.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include #include @@ -55,6 +56,58 @@ static void nativeOverrideHdrTypes(JNIEnv* env, jclass clazz, jobject tokenObjec } } +static void nativeSetHdrConversionMode(JNIEnv* env, jclass clazz, jint hdrConversionMode, + jint preferredHdrOutputType, jintArray autoHdrOutputTypes, + jint autoHdrOutputTypesLength) { + gui::HdrConversionStrategy hdrConversionStrategy; + switch (hdrConversionMode) { + case gui::IHdrConversionConstants::HdrConversionModePassthrough: { + hdrConversionStrategy.set(true); + break; + } + case gui::IHdrConversionConstants::HdrConversionModeAuto: { + jint* autoHdrOutputTypesArray = env->GetIntArrayElements(autoHdrOutputTypes, 0); + std::vector autoHdrOutputTypesVector(autoHdrOutputTypesLength); + for (int i = 0; i < autoHdrOutputTypesLength; i++) { + autoHdrOutputTypesVector[i] = autoHdrOutputTypesArray[i]; + } + hdrConversionStrategy.set( + autoHdrOutputTypesVector); + break; + } + case gui::IHdrConversionConstants::HdrConversionModeForce: { + hdrConversionStrategy.set( + preferredHdrOutputType); + break; + } + } + + SurfaceComposerClient::setHdrConversionStrategy(hdrConversionStrategy); +} + +static jintArray nativeGetSupportedHdrOutputTypes(JNIEnv* env, jclass clazz) { + std::vector hdrConversionCapabilities; + SurfaceComposerClient::getHdrConversionCapabilities(&hdrConversionCapabilities); + + // Extract unique HDR output types. + std::set hdrOutputTypes; + for (const auto& hdrConversionCapability : hdrConversionCapabilities) { + hdrOutputTypes.insert(hdrConversionCapability.outputType); + } + jintArray array = env->NewIntArray(hdrOutputTypes.size()); + if (array == nullptr) { + jniThrowException(env, "java/lang/OutOfMemoryError", nullptr); + return nullptr; + } + jint* arrayValues = env->GetIntArrayElements(array, 0); + int index = 0; + for (auto hdrOutputType : hdrOutputTypes) { + arrayValues[index++] = static_cast(hdrOutputType); + } + env->ReleaseIntArrayElements(array, arrayValues, 0); + return array; +} + static jlongArray nativeGetPhysicalDisplayIds(JNIEnv* env, jclass clazz) { const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds(); ScopedLongArrayRW values(env, env->NewLongArray(displayIds.size())); @@ -91,6 +144,10 @@ static const JNINativeMethod sDisplayMethods[] = { (void*)nativeGetPhysicalDisplayIds }, {"nativeGetPhysicalDisplayToken", "(J)Landroid/os/IBinder;", (void*)nativeGetPhysicalDisplayToken }, + {"nativeSetHdrConversionMode", "(II[II)V", + (void*)nativeSetHdrConversionMode }, + {"nativeGetSupportedHdrOutputTypes", "()[I", + (void*)nativeGetSupportedHdrOutputTypes }, // clang-format on };