From 896f3a25b93ff38677aa3d28477b8f43c027b2b0 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Mon, 29 Jan 2024 10:39:54 -0800 Subject: Introduce eCanOccludePresentation layer flag Sets a property on a layer hierarchy indicating that its visible region should be considered when computing TrustedPresentation Thresholds. This property is set on a layer and inherited by all its children. The property is then passed via windowinfos so the TrustedPresentation controller can determine which windows to use when computing the thresholds. Test: presubmit Bug: b/275574214 Change-Id: Ia59d5053a4e7fcbc725d7c54401c2038d0622558 --- core/java/android/view/InputWindowHandle.java | 8 ++++ core/java/android/view/SurfaceControl.java | 47 ++++++++++++++++++++++ .../android_hardware_input_InputWindowHandle.cpp | 6 +++ 3 files changed, 61 insertions(+) diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java index 59ec60545d6d..9db1060abad4 100644 --- a/core/java/android/view/InputWindowHandle.java +++ b/core/java/android/view/InputWindowHandle.java @@ -161,6 +161,12 @@ public final class InputWindowHandle { */ public float alpha; + /** + * Sets a property on this window indicating that its visible region should be considered when + * computing TrustedPresentation Thresholds. + */ + public boolean canOccludePresentation; + /** * The input token for the window to which focus should be transferred when this input window * can be successfully focused. If null, this input window will not transfer its focus to @@ -205,6 +211,7 @@ public final class InputWindowHandle { focusTransferTarget = other.focusTransferTarget; contentSize = new Size(other.contentSize.getWidth(), other.contentSize.getHeight()); alpha = other.alpha; + canOccludePresentation = other.canOccludePresentation; } @Override @@ -219,6 +226,7 @@ public final class InputWindowHandle { .append(", isClone=").append((inputConfig & InputConfig.CLONE) != 0) .append(", contentSize=").append(contentSize) .append(", alpha=").append(alpha) + .append(", canOccludePresentation=").append(canOccludePresentation) .toString(); } diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 3ed03859ffa6..3c0ac06ae13f 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -168,6 +168,8 @@ public final class SurfaceControl implements Parcelable { boolean isTrustedOverlay); private static native void nativeSetDropInputMode( long transactionObj, long nativeObject, int flags); + private static native void nativeSetCanOccludePresentation(long transactionObj, + long nativeObject, boolean canOccludePresentation); private static native void nativeSurfaceFlushJankData(long nativeSurfaceObject); private static native boolean nativeClearContentFrameStats(long nativeObject); private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats); @@ -588,6 +590,28 @@ public final class SurfaceControl implements Parcelable { */ public static final int DISPLAY_DECORATION = 0x00000200; + /** + * Ignore any destination frame set on the layer. This is used when the buffer scaling mode + * is freeze and the destination frame is applied asynchronously with the buffer submission. + * This is needed to maintain compatibility for SurfaceView scaling behavior. + * See SurfaceView scaling behavior for more details. + * @hide + */ + public static final int IGNORE_DESTINATION_FRAME = 0x00000400; + + /** + * Special casing for layer that is a refresh rate indicator + * @hide + */ + public static final int LAYER_IS_REFRESH_RATE_INDICATOR = 0x00000800; + + /** + * Sets a property on this layer indicating that its visible region should be considered when + * computing TrustedPresentation Thresholds + * @hide + */ + public static final int CAN_OCCLUDE_PRESENTATION = 0x00001000; + /** * Surface creation flag: Creates a surface where color components are interpreted * as "non pre-multiplied" by their alpha channel. Of course this flag is @@ -4162,6 +4186,29 @@ public final class SurfaceControl implements Parcelable { return this; } + /** + * Sets a property on this SurfaceControl and all its children indicating that the visible + * region of this SurfaceControl should be considered when computing TrustedPresentation + * Thresholds. + *

+ * API Guidance: + * The goal of this API is to identify windows that can be used to occlude content on + * another window. This includes windows controlled by the user or the system. If the window + * is transient, like Toast or notification shade, the window should not set this flag since + * the user or the app cannot use the window to occlude content in a persistent manner. All + * apps should have this flag set. + *

+ * The caller must hold the ACCESS_SURFACE_FLINGER permission. + * @hide + */ + public Transaction setCanOccludePresentation(SurfaceControl sc, + boolean canOccludePresentation) { + checkPreconditions(sc); + final int value = (canOccludePresentation) ? CAN_OCCLUDE_PRESENTATION : 0; + nativeSetFlags(mNativeObject, sc.mNativeObject, value, CAN_OCCLUDE_PRESENTATION); + return this; + } + /** * Sends a flush jank data transaction for the given surface. * @hide diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp index ae23942f2500..bed776836043 100644 --- a/core/jni/android_hardware_input_InputWindowHandle.cpp +++ b/core/jni/android_hardware_input_InputWindowHandle.cpp @@ -75,6 +75,7 @@ static struct { jfieldID windowToken; jfieldID focusTransferTarget; jfieldID alpha; + jfieldID canOccludePresentation; } gInputWindowHandleClassInfo; static struct { @@ -327,6 +328,8 @@ jobject android_view_InputWindowHandle_fromWindowInfo(JNIEnv* env, gui::WindowIn javaObjectForIBinder(env, windowInfo.windowToken)); env->SetFloatField(inputWindowHandle, gInputWindowHandleClassInfo.alpha, windowInfo.alpha); + env->SetBooleanField(inputWindowHandle, gInputWindowHandleClassInfo.canOccludePresentation, + windowInfo.canOccludePresentation); return inputWindowHandle; } @@ -451,6 +454,9 @@ int register_android_view_InputWindowHandle(JNIEnv* env) { GET_FIELD_ID(gInputWindowHandleClassInfo.alpha, clazz, "alpha", "F"); + GET_FIELD_ID(gInputWindowHandleClassInfo.canOccludePresentation, clazz, + "canOccludePresentation", "Z"); + jclass surfaceControlClazz; FIND_CLASS(surfaceControlClazz, "android/view/SurfaceControl"); GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegionSurfaceControl.mNativeObject, -- cgit v1.2.3-59-g8ed1b From e823afc21cba1d3bacce94094680f2c5d45a93e3 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 26 Jan 2024 12:59:37 -0800 Subject: Use CanOccludePresentation state to calculate TrustedPresentationThresholds Switch from window token to using CanOccludePresentation state to calculate TrustedPresentationThresholds. All app windows should have this flag set. If the window is transient, and is a system window like Toast or notification shade, the window should not set this flag since the user or the app cannot use the window to occlude content in a persistent manner. Test: presubmit Bug: b/275574214 Change-Id: Icc9b2ef19ae0c9cdc54afd643669b6154d8ad90e --- .../wm/TrustedPresentationListenerController.java | 23 +--------------------- .../java/com/android/server/wm/WindowState.java | 10 +++------- .../android/server/testutils/StubTransaction.java | 6 ++++++ 3 files changed, 10 insertions(+), 29 deletions(-) diff --git a/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java b/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java index 1688a1a91114..817901f96ad4 100644 --- a/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java +++ b/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java @@ -32,7 +32,6 @@ import android.os.HandlerThread; import android.os.IBinder; import android.os.RemoteException; import android.util.ArrayMap; -import android.util.ArraySet; import android.util.IntArray; import android.util.Pair; import android.util.Size; @@ -159,10 +158,6 @@ public class TrustedPresentationListenerController { private InputWindowHandle[] mLastWindowHandles; - private final Object mIgnoredWindowTokensLock = new Object(); - - private final ArraySet mIgnoredWindowTokens = new ArraySet<>(); - private void startHandlerThreadIfNeeded() { synchronized (mHandlerThreadLock) { if (mHandler == null) { @@ -173,18 +168,6 @@ public class TrustedPresentationListenerController { } } - void addIgnoredWindowTokens(IBinder token) { - synchronized (mIgnoredWindowTokensLock) { - mIgnoredWindowTokens.add(token); - } - } - - void removeIgnoredWindowTokens(IBinder token) { - synchronized (mIgnoredWindowTokensLock) { - mIgnoredWindowTokens.remove(token); - } - } - void registerListener(IBinder window, ITrustedPresentationListener listener, TrustedPresentationThresholds thresholds, int id) { startHandlerThreadIfNeeded(); @@ -271,12 +254,8 @@ public class TrustedPresentationListenerController { ArrayMap> listenerUpdates = new ArrayMap<>(); - ArraySet ignoredWindowTokens; - synchronized (mIgnoredWindowTokensLock) { - ignoredWindowTokens = new ArraySet<>(mIgnoredWindowTokens); - } for (var windowHandle : mLastWindowHandles) { - if (ignoredWindowTokens.contains(windowHandle.getWindowToken())) { + if (!windowHandle.canOccludePresentation) { ProtoLog.v(WM_DEBUG_TPL, "Skipping %s", windowHandle.name); continue; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 24e50c54aa61..f5806c07c572 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1148,10 +1148,6 @@ class WindowState extends WindowContainer implements WindowManagerP parentWindow.addChild(this, sWindowSubLayerComparator); } - if (token.mRoundedCornerOverlay) { - mWmService.mTrustedPresentationListenerController.addIgnoredWindowTokens( - getWindowToken()); - } } @Override @@ -1163,6 +1159,9 @@ class WindowState extends WindowContainer implements WindowManagerP if (secureWindowState()) { getPendingTransaction().setSecure(mSurfaceControl, isSecureLocked()); } + // All apps should be considered as occluding when computing TrustedPresentation Thresholds. + final boolean canOccludePresentation = !mSession.mCanAddInternalSystemWindow; + getPendingTransaction().setCanOccludePresentation(mSurfaceControl, canOccludePresentation); } void updateTrustedOverlay() { @@ -2344,9 +2343,6 @@ class WindowState extends WindowContainer implements WindowManagerP mSession.onWindowRemoved(this); mWmService.postWindowRemoveCleanupLocked(this); - mWmService.mTrustedPresentationListenerController.removeIgnoredWindowTokens( - getWindowToken()); - consumeInsetsChange(); } diff --git a/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java b/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java index b8dcecdbfb95..e27bb4c8c3b6 100644 --- a/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java +++ b/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java @@ -320,4 +320,10 @@ public class StubTransaction extends SurfaceControl.Transaction { mWindowInfosReportedListeners.add(listener); return this; } + + @Override + public SurfaceControl.Transaction setCanOccludePresentation(SurfaceControl sc, + boolean canOccludePresentation) { + return this; + } } -- cgit v1.2.3-59-g8ed1b