Merge "Add minimal post processing API to framework"
diff --git a/api/current.txt b/api/current.txt
index 11ae3d5..8f0002b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1061,6 +1061,7 @@
field public static final int popupWindowStyle = 16842870; // 0x1010076
field public static final int port = 16842793; // 0x1010029
field public static final int positiveButtonText = 16843253; // 0x10101f5
+ field public static final int preferMinimalPostProcessing = 16844300; // 0x101060c
field public static final int preferenceCategoryStyle = 16842892; // 0x101008c
field public static final int preferenceFragmentStyle = 16844038; // 0x1010506
field public static final int preferenceInformationStyle = 16842893; // 0x101008d
@@ -11185,6 +11186,7 @@
field public String parentActivityName;
field public String permission;
field public int persistableMode;
+ field public boolean preferMinimalPostProcessing;
field public int screenOrientation;
field public int softInputMode;
field public String targetActivity;
@@ -49518,6 +49520,7 @@
method @Deprecated public float[] getSupportedRefreshRates();
method @Deprecated public int getWidth();
method public boolean isHdr();
+ method public boolean isMinimalPostProcessingSupported();
method public boolean isValid();
method public boolean isWideColorGamut();
field public static final int DEFAULT_DISPLAY = 0; // 0x0
@@ -52543,6 +52546,7 @@
method public abstract void setNavigationBarColor(@ColorInt int);
method public void setNavigationBarContrastEnforced(boolean);
method public void setNavigationBarDividerColor(@ColorInt int);
+ method public void setPreferMinimalPostProcessing(boolean);
method public void setReenterTransition(android.transition.Transition);
method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
method public final void setRestrictedCaptionAreaListener(android.view.Window.OnRestrictedCaptionAreaChangedListener);
@@ -52860,6 +52864,7 @@
field public int layoutInDisplayCutoutMode;
field @Deprecated public int memoryType;
field public String packageName;
+ field public boolean preferMinimalPostProcessing;
field public int preferredDisplayModeId;
field @Deprecated public float preferredRefreshRate;
field public int rotationAnimation;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 577272e..9711e06 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -7855,6 +7855,7 @@
mCurrentConfig = config;
mWindow.setColorMode(info.colorMode);
+ mWindow.setPreferMinimalPostProcessing(info.preferMinimalPostProcessing);
setAutofillOptions(application.getAutofillOptions());
setContentCaptureOptions(application.getContentCaptureOptions());
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 26193f6..fe59f05 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -290,6 +290,34 @@
public int colorMode = COLOR_MODE_DEFAULT;
/**
+ * Indicates whether the activity wants the connected display to do minimal post processing on
+ * the produced image or video frames. This will only be requested if this activity's main
+ * window is visible on the screen.
+ *
+ * <p>This setting should be used when low latency has a higher priority than image enhancement
+ * processing (e.g. for games or video conferencing).
+ *
+ * <p>If the Display sink is connected via HDMI, the device will begin to send infoframes with
+ * Auto Low Latency Mode enabled and Game Content Type. This will switch the connected display
+ * to a minimal image processing mode (if available), which reduces latency, improving the user
+ * experience for gaming or video conferencing applications. For more information, see HDMI 2.1
+ * specification.
+ *
+ * <p>If the Display sink has an internal connection or uses some other protocol than HDMI,
+ * effects may be similar but implementation-defined.
+ *
+ * <p>The ability to switch to a mode with minimal post proessing may be disabled by a user
+ * setting in the system settings menu. In that case, this field is ignored and the display will
+ * remain in its current mode.
+ *
+ * <p>Set from attribute {@link android.R.attr#preferMinimalPostProcessing}.
+ *
+ * @see android.view.WindowManager.LayoutParams#preferMinimalPostProcessing
+ * @see android.view.Display#isMinimalPostProcessingSupported
+ */
+ public boolean preferMinimalPostProcessing = false;
+
+ /**
* Bit in {@link #flags} indicating whether this activity is able to
* run in multiple processes. If
* true, the system may instantiate it in the some process as the
@@ -1004,6 +1032,7 @@
requestedVrComponent = orig.requestedVrComponent;
rotationAnimation = orig.rotationAnimation;
colorMode = orig.colorMode;
+ preferMinimalPostProcessing = orig.preferMinimalPostProcessing;
maxAspectRatio = orig.maxAspectRatio;
minAspectRatio = orig.minAspectRatio;
}
@@ -1231,6 +1260,7 @@
dest.writeInt(colorMode);
dest.writeFloat(maxAspectRatio);
dest.writeFloat(minAspectRatio);
+ dest.writeBoolean(preferMinimalPostProcessing);
}
/**
@@ -1349,6 +1379,7 @@
colorMode = source.readInt();
maxAspectRatio = source.readFloat();
minAspectRatio = source.readFloat();
+ preferMinimalPostProcessing = source.readBoolean();
}
/**
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index c955137..df2d0dd 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -24,7 +24,6 @@
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
-import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
@@ -151,11 +150,14 @@
* has a preference.
* @param requestedModeId The preferred mode id for the top-most visible window that has a
* preference.
+ * @param preferMinimalPostProcessing Whether there is a visible window on the screen that wants
+ * minimal post processing.
* @param inTraversal True if called from WindowManagerService during a window traversal
* prior to call to performTraversalInTransactionFromWindowManager.
*/
public abstract void setDisplayProperties(int displayId, boolean hasContent,
- float requestedRefreshRate, int requestedModeId, boolean inTraversal);
+ float requestedRefreshRate, int requestedModeId, boolean preferMinimalPostProcessing,
+ boolean inTraversal);
/**
* Applies an offset to the contents of a display, for example to avoid burn-in.
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index ba25093..117b971 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -21,6 +21,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
@@ -857,6 +858,31 @@
}
/**
+ * <p> Returns true if the connected display can be switched into a mode with minimal
+ * post processing. </p>
+ *
+ * <p> If the Display sink is connected via HDMI, this method will return true if the
+ * display supports either Auto Low Latency Mode or Game Content Type.
+ *
+ * <p> If the Display sink has an internal connection or uses some other protocol than
+ * HDMI, this method will return true if the sink can be switched into an
+ * implementation-defined low latency image processing mode. </p>
+ *
+ * <p> The ability to switch to a mode with minimal post processing may be disabled
+ * by a user setting in the system settings menu. In that case, this method returns
+ * false. </p>
+ *
+ * @see android.view.Window#setPreferMinimalPostProcessing
+ */
+ @SuppressLint("VisiblySynchronized")
+ public boolean isMinimalPostProcessingSupported() {
+ synchronized (this) {
+ updateDisplayInfoLocked();
+ return mDisplayInfo.minimalPostProcessingSupported;
+ }
+ }
+
+ /**
* Request the display applies a color mode.
* @hide
*/
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 04e82c7..b84a7b5 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -184,6 +184,14 @@
public Display.HdrCapabilities hdrCapabilities;
/**
+ * Indicates whether the display can be switched into a mode with minimal post
+ * processing.
+ *
+ * @see android.view.Display#isMinimalPostProcessingSupported
+ */
+ public boolean minimalPostProcessingSupported;
+
+ /**
* The logical display density which is the basis for density-independent
* pixels.
*/
@@ -305,6 +313,7 @@
&& colorMode == other.colorMode
&& Arrays.equals(supportedColorModes, other.supportedColorModes)
&& Objects.equals(hdrCapabilities, other.hdrCapabilities)
+ && minimalPostProcessingSupported == other.minimalPostProcessingSupported
&& logicalDensityDpi == other.logicalDensityDpi
&& physicalXDpi == other.physicalXDpi
&& physicalYDpi == other.physicalYDpi
@@ -346,6 +355,7 @@
supportedColorModes = Arrays.copyOf(
other.supportedColorModes, other.supportedColorModes.length);
hdrCapabilities = other.hdrCapabilities;
+ minimalPostProcessingSupported = other.minimalPostProcessingSupported;
logicalDensityDpi = other.logicalDensityDpi;
physicalXDpi = other.physicalXDpi;
physicalYDpi = other.physicalYDpi;
@@ -388,6 +398,7 @@
supportedColorModes[i] = source.readInt();
}
hdrCapabilities = source.readParcelable(null);
+ minimalPostProcessingSupported = source.readBoolean();
logicalDensityDpi = source.readInt();
physicalXDpi = source.readFloat();
physicalYDpi = source.readFloat();
@@ -430,6 +441,7 @@
dest.writeInt(supportedColorModes[i]);
}
dest.writeParcelable(hdrCapabilities, flags);
+ dest.writeBoolean(minimalPostProcessingSupported);
dest.writeInt(logicalDensityDpi);
dest.writeFloat(physicalXDpi);
dest.writeFloat(physicalYDpi);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 87628da..db83ede 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -170,6 +170,8 @@
private static native int nativeGetActiveColorMode(IBinder displayToken);
private static native boolean nativeSetActiveColorMode(IBinder displayToken,
int colorMode);
+ private static native void nativeSetAutoLowLatencyMode(IBinder displayToken, boolean on);
+ private static native void nativeSetGameContentType(IBinder displayToken, boolean on);
private static native void nativeSetDisplayPowerMode(
IBinder displayToken, int mode);
private static native void nativeDeferTransactionUntil(long transactionObj, long nativeObject,
@@ -187,6 +189,9 @@
private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);
+ private static native boolean nativeGetAutoLowLatencyModeSupport(IBinder displayToken);
+ private static native boolean nativeGetGameContentTypeSupport(IBinder displayToken);
+
private static native void nativeSetInputWindowInfo(long transactionObj, long nativeObject,
InputWindowHandle handle);
@@ -1670,6 +1675,28 @@
/**
* @hide
*/
+ public static void setAutoLowLatencyMode(IBinder displayToken, boolean on) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ nativeSetAutoLowLatencyMode(displayToken, on);
+ }
+
+ /**
+ * @hide
+ */
+ public static void setGameContentType(IBinder displayToken, boolean on) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ nativeSetGameContentType(displayToken, on);
+ }
+
+ /**
+ * @hide
+ */
@UnsupportedAppUsage
public static void setDisplayProjection(IBinder displayToken,
int orientation, Rect layerStackRect, Rect displayRect) {
@@ -1721,6 +1748,28 @@
/**
* @hide
*/
+ public static boolean getAutoLowLatencyModeSupport(IBinder displayToken) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ return nativeGetAutoLowLatencyModeSupport(displayToken);
+ }
+
+ /**
+ * @hide
+ */
+ public static boolean getGameContentTypeSupport(IBinder displayToken) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ return nativeGetGameContentTypeSupport(displayToken);
+ }
+
+ /**
+ * @hide
+ */
@UnsupportedAppUsage
public static IBinder createDisplay(String name, boolean secure) {
if (name == null) {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index d79abc2..a168c07 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1197,6 +1197,44 @@
}
/**
+ * If {@code isPreferred} is true, this method requests that the connected display does minimal
+ * post processing when this window is visible on the screen. Otherwise, it requests that the
+ * display switches back to standard image processing.
+ *
+ * <p> By default, the display does not do minimal post processing and if this is desired, this
+ * method should not be used. It should be used with {@code isPreferred=true} when low
+ * latency has a higher priority than image enhancement processing (e.g. for games or video
+ * conferencing). The display will automatically go back into standard image processing mode
+ * when no window requesting minimal posst processing is visible on screen anymore.
+ * {@code setPreferMinimalPostProcessing(false)} can be used if
+ * {@code setPreferMinimalPostProcessing(true)} was previously called for this window and
+ * minimal post processing is no longer required.
+ *
+ * <p>If the Display sink is connected via HDMI, the device will begin to send infoframes with
+ * Auto Low Latency Mode enabled and Game Content Type. This will switch the connected display
+ * to a minimal image processing mode (if available), which reduces latency, improving the user
+ * experience for gaming or video conferencing applications. For more information, see HDMI 2.1
+ * specification.
+ *
+ * <p>If the Display sink has an internal connection or uses some other protocol than HDMI,
+ * effects may be similar but implementation-defined.
+ *
+ * <p>The ability to switch to a mode with minimal post proessing may be disabled by a user
+ * setting in the system settings menu. In that case, this method does nothing.
+ *
+ * @see android.content.pm.ActivityInfo#preferMinimalPostProcessing
+ * @see android.view.Display#isMinimalPostProcessingSupported
+ * @see android.view.WindowManager.LayoutParams#preferMinimalPostProcessing
+ *
+ * @param isPreferred Indicates whether minimal post processing is preferred for this window
+ * ({@code isPreferred=true}) or not ({@code isPreferred=false}).
+ */
+ public void setPreferMinimalPostProcessing(boolean isPreferred) {
+ mWindowAttributes.preferMinimalPostProcessing = isPreferred;
+ dispatchWindowAttributesChanged(mWindowAttributes);
+ }
+
+ /**
* Returns the requested color mode of the window, one of
* {@link ActivityInfo#COLOR_MODE_DEFAULT}, {@link ActivityInfo#COLOR_MODE_WIDE_COLOR_GAMUT}
* or {@link ActivityInfo#COLOR_MODE_HDR}. If {@link ActivityInfo#COLOR_MODE_WIDE_COLOR_GAMUT}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 9d5f98e..cbfe52b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -2573,6 +2573,33 @@
public long hideTimeoutMilliseconds = -1;
/**
+ * Indicates whether this window wants the connected display to do minimal post processing
+ * on the produced image or video frames. This will only be requested if the window is
+ * visible on the screen.
+ *
+ * <p>This setting should be used when low latency has a higher priority than image
+ * enhancement processing (e.g. for games or video conferencing).
+ *
+ * <p>If the Display sink is connected via HDMI, the device will begin to send infoframes
+ * with Auto Low Latency Mode enabled and Game Content Type. This will switch the connected
+ * display to a minimal image processing mode (if available), which reduces latency,
+ * improving the user experience for gaming or video conferencing applications. For more
+ * information, see HDMI 2.1 specification.
+ *
+ * <p>If the Display sink has an internal connection or uses some other protocol than HDMI,
+ * effects may be similar but implementation-defined.
+ *
+ * <p>The ability to switch to a mode with minimal post proessing may be disabled by a user
+ * setting in the system settings menu. In that case, this field is ignored and the display
+ * will remain in its current mode.
+ *
+ * @see android.content.pm.ActivityInfo#preferMinimalPostProcessing
+ * @see android.view.Display#isMinimalPostProcessingSupported
+ * @see android.view.Window#setPreferMinimalPostProcessing
+ */
+ public boolean preferMinimalPostProcessing = false;
+
+ /**
* The color mode requested by this window. The target display may
* not be able to honor the request. When the color mode is not set
* to {@link ActivityInfo#COLOR_MODE_DEFAULT}, it might override the
@@ -2754,6 +2781,7 @@
out.writeLong(hideTimeoutMilliseconds);
out.writeInt(insetsFlags.appearance);
out.writeInt(insetsFlags.behavior);
+ out.writeBoolean(preferMinimalPostProcessing);
}
public static final @android.annotation.NonNull Parcelable.Creator<LayoutParams> CREATOR
@@ -2811,6 +2839,7 @@
hideTimeoutMilliseconds = in.readLong();
insetsFlags.appearance = in.readInt();
insetsFlags.behavior = in.readInt();
+ preferMinimalPostProcessing = in.readBoolean();
}
@SuppressWarnings({"PointlessBitwiseExpression"})
@@ -2856,6 +2885,8 @@
public static final int COLOR_MODE_CHANGED = 1 << 26;
/** {@hide} */
public static final int INSET_FLAGS_CHANGED = 1 << 27;
+ /** {@hide} */
+ public static final int MINIMAL_POST_PROCESSING_PREFERENCE_CHANGED = 1 << 28;
// internal buffer to backup/restore parameters under compatibility mode.
private int[] mCompatibilityParamsBackup = null;
@@ -3036,6 +3067,11 @@
changes |= COLOR_MODE_CHANGED;
}
+ if (preferMinimalPostProcessing != o.preferMinimalPostProcessing) {
+ preferMinimalPostProcessing = o.preferMinimalPostProcessing;
+ changes |= MINIMAL_POST_PROCESSING_PREFERENCE_CHANGED;
+ }
+
// This can't change, it's only set at window creation time.
hideTimeoutMilliseconds = o.hideTimeoutMilliseconds;
@@ -3175,6 +3211,10 @@
if (mColorMode != COLOR_MODE_DEFAULT) {
sb.append(" colorMode=").append(ActivityInfo.colorModeToString(mColorMode));
}
+ if (preferMinimalPostProcessing) {
+ sb.append(" preferMinimalPostProcessing=");
+ sb.append(preferMinimalPostProcessing);
+ }
sb.append(System.lineSeparator());
sb.append(prefix).append(" fl=").append(
ViewDebug.flagsToString(LayoutParams.class, "flags", flags));
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index c6e678ab..ec8d4ab 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -1199,6 +1199,34 @@
capabilities.getDesiredMaxAverageLuminance(), capabilities.getDesiredMinLuminance());
}
+static jboolean nativeGetAutoLowLatencyModeSupport(JNIEnv* env, jclass clazz, jobject tokenObject) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
+ if (token == NULL) return NULL;
+
+ return SurfaceComposerClient::getAutoLowLatencyModeSupport(token);
+}
+
+static jboolean nativeGetGameContentTypeSupport(JNIEnv* env, jclass clazz, jobject tokenObject) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
+ if (token == NULL) return NULL;
+
+ return SurfaceComposerClient::getGameContentTypeSupport(token);
+}
+
+static void nativeSetAutoLowLatencyMode(JNIEnv* env, jclass clazz, jobject tokenObject, jboolean on) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
+ if (token == NULL) return;
+
+ SurfaceComposerClient::setAutoLowLatencyMode(token, on);
+}
+
+static void nativeSetGameContentType(JNIEnv* env, jclass clazz, jobject tokenObject, jboolean on) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
+ if (token == NULL) return;
+
+ SurfaceComposerClient::setGameContentType(token, on);
+}
+
static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);
if (parcel == NULL) {
@@ -1402,6 +1430,14 @@
(void*)nativeGetActiveColorMode},
{"nativeSetActiveColorMode", "(Landroid/os/IBinder;I)Z",
(void*)nativeSetActiveColorMode},
+ {"nativeGetAutoLowLatencyModeSupport", "(Landroid/os/IBinder;)Z",
+ (void*)nativeGetAutoLowLatencyModeSupport },
+ {"nativeSetAutoLowLatencyMode", "(Landroid/os/IBinder;Z)V",
+ (void*)nativeSetAutoLowLatencyMode },
+ {"nativeGetGameContentTypeSupport", "(Landroid/os/IBinder;)Z",
+ (void*)nativeGetGameContentTypeSupport },
+ {"nativeSetGameContentType", "(Landroid/os/IBinder;Z)V",
+ (void*)nativeSetGameContentType },
{"nativeGetCompositionDataspaces", "()[I",
(void*)nativeGetCompositionDataspaces},
{"nativeGetHdrCapabilities", "(Landroid/os/IBinder;)Landroid/view/Display$HdrCapabilities;",
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 166cde0..1025f81 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2494,6 +2494,30 @@
<enum name="hdr" value="2" />
</attr>
<attr name="forceQueryable" format="boolean" />
+ <!-- Indicates whether the activity wants the connected display to do minimal
+ post processing on the produced image or video frames. This will only be
+ requested if this activity's main window is visible on the screen.
+
+ <p> This setting should be used when low latency has a higher priority than
+ image enhancement processing (e.g. for games or video conferencing).
+
+ <p> If the Display sink is connected via HDMI, the device will begin to
+ send infoframes with Auto Low Latency Mode enabled and Game Content Type.
+ This will switch the connected display to a minimal image processing mode
+ (if available), which reduces latency, improving the user experience for
+ gaming or video conferencing applications. For more information,
+ see HDMI 2.1 specification.
+
+ <p> If the Display sink has an internal connection or uses some other
+ protocol than HDMI, effects may be similar but implementation-defined.
+
+ <p> The ability to switch to a mode with minimal post proessing may be
+ disabled by a user setting in the system settings menu. In that case,
+ this field is ignored and the display will remain in its current
+ mode.
+
+ <p> See {@link android.content.pm.ActivityInfo #preferMinimalPostProcessing} -->
+ <attr name="preferMinimalPostProcessing" format="boolean"/>
</declare-styleable>
<!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 78c4efe..d753630 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3051,6 +3051,10 @@
<public name="accessibilitySystemActionLockScreen" />
<public name="accessibilitySystemActionTakeScreenshot" />
</public-group>
+
+ <public-group type="attr" first-id="0x0101060c">
+ <public name="preferMinimalPostProcessing"/>
+ </public-group>
<!-- ===============================================================
DO NOT ADD UN-GROUPED ITEMS HERE
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 7ce63c5..af68403 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -157,6 +157,24 @@
public void setRequestedColorModeLocked(int colorMode) {
}
+ /**
+ * Sends the Auto Low Latency Mode (ALLM) signal over HDMI, or requests an internal display to
+ * switch to a low-latency mode.
+ *
+ * @param on Whether to set ALLM on or off.
+ */
+ public void setAutoLowLatencyModeLocked(boolean on) {
+ }
+
+ /**
+ * Sends a ContentType=Game signal over HDMI, or requests an internal display to switch to a
+ * game mode (generally lower latency).
+ *
+ * @param on Whether to send a ContentType=Game signal or not
+ */
+ public void setGameContentTypeLocked(boolean on) {
+ }
+
public void onOverlayChangedLocked() {
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 729ea17..ac41434 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -207,6 +207,16 @@
public Display.HdrCapabilities hdrCapabilities;
/**
+ * Indicates whether this display supports Auto Low Latency Mode.
+ */
+ public boolean allmSupported;
+
+ /**
+ * Indicates whether this display suppors Game content type.
+ */
+ public boolean gameContentTypeSupported;
+
+ /**
* The nominal apparent density of the display in DPI used for layout calculations.
* This density is sensitive to the viewing distance. A big TV and a tablet may have
* the same apparent density even though the pixels on the TV are much bigger than
@@ -337,6 +347,8 @@
|| !Arrays.equals(supportedModes, other.supportedModes)
|| !Arrays.equals(supportedColorModes, other.supportedColorModes)
|| !Objects.equals(hdrCapabilities, other.hdrCapabilities)
+ || allmSupported != other.allmSupported
+ || gameContentTypeSupported != other.gameContentTypeSupported
|| densityDpi != other.densityDpi
|| xDpi != other.xDpi
|| yDpi != other.yDpi
@@ -371,6 +383,8 @@
colorMode = other.colorMode;
supportedColorModes = other.supportedColorModes;
hdrCapabilities = other.hdrCapabilities;
+ allmSupported = other.allmSupported;
+ gameContentTypeSupported = other.gameContentTypeSupported;
densityDpi = other.densityDpi;
xDpi = other.xDpi;
yDpi = other.yDpi;
@@ -400,6 +414,8 @@
sb.append(", colorMode ").append(colorMode);
sb.append(", supportedColorModes ").append(Arrays.toString(supportedColorModes));
sb.append(", HdrCapabilities ").append(hdrCapabilities);
+ sb.append(", allmSupported ").append(allmSupported);
+ sb.append(", gameContentTypeSupported ").append(gameContentTypeSupported);
sb.append(", density ").append(densityDpi);
sb.append(", ").append(xDpi).append(" x ").append(yDpi).append(" dpi");
sb.append(", appVsyncOff ").append(appVsyncOffsetNanos);
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index d20191d..3e8a726 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -569,6 +569,23 @@
}
}
+ private void setPreferMinimalPostProcessingLocked(int displayId, boolean isPreferred) {
+ LogicalDisplay display = mLogicalDisplays.get(displayId);
+ if (display != null) {
+ DisplayDeviceInfo info =
+ display.getPrimaryDisplayDeviceLocked().getDisplayDeviceInfoLocked();
+
+ if (info.allmSupported) {
+ display.setAutoLowLatencyMode(isPreferred);
+ }
+ if (info.gameContentTypeSupported) {
+ display.setGameContentType(isPreferred);
+ }
+
+ scheduleTraversalLocked(false);
+ }
+ }
+
private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
synchronized (mSyncRoot) {
LogicalDisplay display = mLogicalDisplays.get(displayId);
@@ -1192,7 +1209,8 @@
}
private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
- float requestedRefreshRate, int requestedModeId, boolean inTraversal) {
+ float requestedRefreshRate, int requestedModeId, boolean preferMinimalPostProcessing,
+ boolean inTraversal) {
synchronized (mSyncRoot) {
LogicalDisplay display = mLogicalDisplays.get(displayId);
if (display == null) {
@@ -1215,6 +1233,8 @@
}
mDisplayModeDirector.getAppRequestObserver().setAppRequestedMode(
displayId, requestedModeId);
+
+ setPreferMinimalPostProcessingLocked(displayId, preferMinimalPostProcessing);
}
}
@@ -2343,6 +2363,7 @@
}
private final class LocalService extends DisplayManagerInternal {
+
@Override
public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager) {
@@ -2431,9 +2452,10 @@
@Override
public void setDisplayProperties(int displayId, boolean hasContent,
- float requestedRefreshRate, int requestedMode, boolean inTraversal) {
+ float requestedRefreshRate, int requestedMode, boolean preferMinimalPostProcessing,
+ boolean inTraversal) {
setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
- requestedMode, inTraversal);
+ requestedMode, preferMinimalPostProcessing, inTraversal);
}
@Override
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 308c755..86ba845 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -181,6 +181,10 @@
private int mActiveColorMode;
private boolean mActiveColorModeInvalid;
private Display.HdrCapabilities mHdrCapabilities;
+ private boolean mAllmSupported;
+ private boolean mGameContentTypeSupported;
+ private boolean mAllmRequested;
+ private boolean mGameContentTypeRequested;
private boolean mSidekickActive;
private SidekickInternal mSidekickInternal;
@@ -204,6 +208,8 @@
mBacklight = null;
}
mHdrCapabilities = SurfaceControl.getHdrCapabilities(displayToken);
+ mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken);
+ mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken);
}
@Override
@@ -397,6 +403,8 @@
mInfo.defaultModeId = mDefaultModeId;
mInfo.supportedModes = getDisplayModes(mSupportedModes);
mInfo.colorMode = mActiveColorMode;
+ mInfo.allmSupported = mAllmSupported;
+ mInfo.gameContentTypeSupported = mGameContentTypeSupported;
mInfo.supportedColorModes =
new int[mSupportedColorModes.size()];
for (int i = 0; i < mSupportedColorModes.size(); i++) {
@@ -767,6 +775,40 @@
}
@Override
+ public void setAutoLowLatencyModeLocked(boolean on) {
+ if (mAllmRequested == on) {
+ return;
+ }
+
+ mAllmRequested = on;
+
+ if (!mAllmSupported) {
+ Slog.d(TAG, "Unable to set ALLM because the connected display "
+ + "does not support ALLM.");
+ return;
+ }
+
+ SurfaceControl.setAutoLowLatencyMode(getDisplayTokenLocked(), on);
+ }
+
+ @Override
+ public void setGameContentTypeLocked(boolean on) {
+ if (mGameContentTypeRequested == on) {
+ return;
+ }
+
+ mGameContentTypeRequested = on;
+
+ if (!mGameContentTypeSupported) {
+ Slog.d(TAG, "Unable to set game content type because the connected "
+ + "display does not support game content type.");
+ return;
+ }
+
+ SurfaceControl.setGameContentType(getDisplayTokenLocked(), on);
+ }
+
+ @Override
public void dumpLocked(PrintWriter pw) {
super.dumpLocked(pw);
pw.println("mPhysicalDisplayId=" + mPhysicalDisplayId);
@@ -782,6 +824,10 @@
pw.println("mState=" + Display.stateToString(mState));
pw.println("mBrightness=" + mBrightness);
pw.println("mBacklight=" + mBacklight);
+ pw.println("mAllmSupported=" + mAllmSupported);
+ pw.println("mAllmRequested=" + mAllmRequested);
+ pw.println("mGameContentTypeSupported" + mGameContentTypeSupported);
+ pw.println("mGameContentTypeRequested" + mGameContentTypeRequested);
pw.println("mDisplayInfos=");
for (int i = 0; i < mDisplayInfos.length; i++) {
pw.println(" " + mDisplayInfos[i]);
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index f4b2dc8..4649374 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -89,6 +89,8 @@
private int[] mAllowedDisplayModes = new int[0];
private int mRequestedColorMode;
+ private boolean mShouldSetAllm;
+ private boolean mShouldSetGameContentType;
// The display offsets to apply to the display projection.
private int mDisplayOffsetX;
@@ -282,6 +284,8 @@
deviceInfo.supportedColorModes,
deviceInfo.supportedColorModes.length);
mBaseDisplayInfo.hdrCapabilities = deviceInfo.hdrCapabilities;
+ mBaseDisplayInfo.minimalPostProcessingSupported =
+ deviceInfo.allmSupported || deviceInfo.gameContentTypeSupported;
mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi;
mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi;
mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi;
@@ -361,6 +365,9 @@
device.setRequestedColorModeLocked(0);
}
+ device.setAutoLowLatencyModeLocked(mShouldSetAllm);
+ device.setGameContentTypeLocked(mShouldSetGameContentType);
+
// Only grab the display info now as it may have been changed based on the requests above.
final DisplayInfo displayInfo = getDisplayInfoLocked();
final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();
@@ -482,6 +489,26 @@
mRequestedColorMode = colorMode;
}
+ /**
+ * Sends the Auto Low Latency Mode (ALLM) signal over HDMI, or requests an internal display to
+ * switch to a low-latency mode.
+ *
+ * @param on Whether to set ALLM on or off.
+ */
+ public void setAutoLowLatencyMode(boolean on) {
+ mShouldSetAllm = on;
+ }
+
+ /**
+ * Sends a ContentType=Game signal over HDMI, or requests an internal display to switch to a
+ * game mode (generally lower latency).
+ *
+ * @param on Whether to send a ContentType=Game signal or not
+ */
+ public void setGameContentType(boolean on) {
+ mShouldSetGameContentType = on;
+ }
+
/** Returns the pending requested color mode. */
public int getRequestedColorModeLocked() {
return mRequestedColorMode;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 9e5734b..fb84832 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -744,6 +744,7 @@
// Update effect.
w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
+
if (!mTmpApplySurfaceChangesTransactionState.obscured) {
final boolean isDisplayed = w.isDisplayedLw();
@@ -774,6 +775,10 @@
mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
= w.mAttrs.preferredRefreshRate;
}
+
+ mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing
+ |= w.mAttrs.preferMinimalPostProcessing;
+
final int preferredModeId = getDisplayPolicy().getRefreshRatePolicy()
.getPreferredModeId(w);
if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
@@ -3620,6 +3625,7 @@
mLastHasContent,
mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
mTmpApplySurfaceChangesTransactionState.preferredModeId,
+ mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,
true /* inTraversal, must call performTraversalInTrans... below */);
final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
@@ -3923,6 +3929,7 @@
boolean displayHasContent;
boolean obscured;
boolean syswin;
+ boolean preferMinimalPostProcessing;
float preferredRefreshRate;
int preferredModeId;
@@ -3930,6 +3937,7 @@
displayHasContent = false;
obscured = false;
syswin = false;
+ preferMinimalPostProcessing = false;
preferredRefreshRate = 0;
preferredModeId = 0;
}