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
diff --git a/core/api/current.txt b/core/api/current.txt
index f50d3ca..65a89fe 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -49502,6 +49502,7 @@
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 8c64e40..a48a103 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -29,6 +29,7 @@
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 @@
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 @@
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<android.hardware.display.HdrConversionMode> 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 b333f5a..08238ca 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -1301,6 +1301,54 @@
}
/**
+ * 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 f038c66..d9db177 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -979,6 +979,39 @@
}
/**
+ * 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
* battery etc.
diff --git a/core/java/android/hardware/display/HdrConversionMode.aidl b/core/java/android/hardware/display/HdrConversionMode.aidl
new file mode 100644
index 0000000..ac89dd6
--- /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 0000000..1accd17
--- /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)}.
+ * <p>
+ * HDR conversion mode has a conversionMode and preferredHdrOutputType. </p><p>
+ * 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.
+ * </p>
+ * @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<HdrConversionMode> 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 28bb35f..0a44f85 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.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 @@
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 689dce8..25863a6 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -2323,6 +2323,10 @@
*/
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.
*/
public static final int HDR_TYPE_DOLBY_VISION = 1;
@@ -2350,6 +2354,7 @@
/** @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 bc40cef..640b84a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -5244,6 +5244,12 @@
<permission android:name="android.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE"
android:protectionLevel="signature" />
+ <!-- Allows an application to modify the HDR conversion mode.
+ @hide
+ @TestApi -->
+ <permission android:name="android.permission.MODIFY_HDR_CONVERSION_MODE"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Allows an application to control VPN.
<p>Not for use by third-party applications.</p>
@hide -->
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index c641a85..43062d4 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -508,6 +508,9 @@
<!-- Permission needed for CTS test - DefaultDisplayModeTest -->
<uses-permission android:name="android.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE" />
+ <!-- Permission needed for CTS test - HdrConversionTest -->
+ <uses-permission android:name="android.permission.MODIFY_HDR_CONVERSION_MODE" />
+
<!-- Permissions needed for manual testing telephony time zone detector behavior -->
<uses-permission android:name="android.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE" />
diff --git a/services/core/java/com/android/server/display/DisplayControl.java b/services/core/java/com/android/server/display/DisplayControl.java
index 864510e..fa9a100 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.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.os.IBinder;
+import android.view.Display;
import java.util.Objects;
@@ -32,6 +33,9 @@
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 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 06b99f8..9ac3c553 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.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 @@
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 @@
}
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 @@
});
}
+ @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 @@
}
}
+ // 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 @@
@Override // Binder call
public int[] getUserDisabledHdrTypes() {
- return mUserDisabledHdrTypes;
+ synchronized (mSyncRoot) {
+ return mUserDisabledHdrTypes;
+ }
}
@Override // Binder call
@@ -3612,6 +3671,40 @@
}
@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(
Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
diff --git a/services/core/jni/com_android_server_display_DisplayControl.cpp b/services/core/jni/com_android_server_display_DisplayControl.cpp
index 1859333..ec42324 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 <android/gui/IHdrConversionConstants.h>
#include <android_util_Binder.h>
#include <gui/SurfaceComposerClient.h>
#include <jni.h>
@@ -55,6 +56,58 @@
}
}
+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<gui::HdrConversionStrategy::Tag::passthrough>(true);
+ break;
+ }
+ case gui::IHdrConversionConstants::HdrConversionModeAuto: {
+ jint* autoHdrOutputTypesArray = env->GetIntArrayElements(autoHdrOutputTypes, 0);
+ std::vector<int> autoHdrOutputTypesVector(autoHdrOutputTypesLength);
+ for (int i = 0; i < autoHdrOutputTypesLength; i++) {
+ autoHdrOutputTypesVector[i] = autoHdrOutputTypesArray[i];
+ }
+ hdrConversionStrategy.set<gui::HdrConversionStrategy::Tag::autoAllowedHdrTypes>(
+ autoHdrOutputTypesVector);
+ break;
+ }
+ case gui::IHdrConversionConstants::HdrConversionModeForce: {
+ hdrConversionStrategy.set<gui::HdrConversionStrategy::Tag::forceHdrConversion>(
+ preferredHdrOutputType);
+ break;
+ }
+ }
+
+ SurfaceComposerClient::setHdrConversionStrategy(hdrConversionStrategy);
+}
+
+static jintArray nativeGetSupportedHdrOutputTypes(JNIEnv* env, jclass clazz) {
+ std::vector<gui::HdrConversionCapability> hdrConversionCapabilities;
+ SurfaceComposerClient::getHdrConversionCapabilities(&hdrConversionCapabilities);
+
+ // Extract unique HDR output types.
+ std::set<int> 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<jint>(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 @@
(void*)nativeGetPhysicalDisplayIds },
{"nativeGetPhysicalDisplayToken", "(J)Landroid/os/IBinder;",
(void*)nativeGetPhysicalDisplayToken },
+ {"nativeSetHdrConversionMode", "(II[II)V",
+ (void*)nativeSetHdrConversionMode },
+ {"nativeGetSupportedHdrOutputTypes", "()[I",
+ (void*)nativeGetSupportedHdrOutputTypes },
// clang-format on
};