From 05ebe2894fdaade99666ddf6acf8f550b3924821 Mon Sep 17 00:00:00 2001 From: Bernardo Rufino Date: Thu, 3 Mar 2022 15:33:20 +0000 Subject: [PATCH] Cap alpha to max if SAW + FLAG_NOT_TOUCHABLE As part of go/untrusted-touches for S, we blocked touches from passing windows of different UIDs regardless of targetSdk. For SAWs, we applied an opacity rule where apps would be able to let touches pass through (usually via FLAG_NOT_TOUCHABLE) as long as their cumulative opacity in the touch area wasn't greater than 0.8. This resulted in some overlay apps being broken, which we expected and saw to some extent in df/dp/beta, but we had reached out and some apps fixed the issue. But the issue seems to be more widespread and OEM has escalated the issue, reporting it to be affecting them more severely (see bug). So, we automatically make SAW + FLAG_NOT_TOUCHABLE windows have 20% transparency to try to honor FLAG_NOT_TOUCHABLE and let touches pass through. Note that if the app has overlapping windows the cumulative opacity would be taken into consideration and the touch could still be blocked, but none among the apps I checked did that. Test: atest -d android.server.wm.WindowUntrustedTouchTest Test: Install and enable you.in.spark.energy.curved, verify touches work in the top part of the screen. Bug: 218777508 Merged-In: I3a74e1cc43a36171ee10fbf68c4bfff538eee661 Change-Id: I3a74e1cc43a36171ee10fbf68c4bfff538eee661 --- .../com/android/server/wm/DisplayPolicy.java | 20 +++++++++++++++++++ .../server/wm/WindowManagerService.java | 20 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 1108c7752777d..2f879c330c2fe 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -914,6 +914,26 @@ public class DisplayPolicy { break; } + if (LayoutParams.isSystemAlertWindowType(attrs.type)) { + float maxOpacity = mService.mMaximumObscuringOpacityForTouch; + if (attrs.alpha > maxOpacity + && (attrs.flags & FLAG_NOT_TOUCHABLE) != 0 + && (attrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) == 0) { + // The app is posting a SAW with the intent of letting touches pass through, but + // they are going to be deemed untrusted and will be blocked. Try to honor the + // intent of letting touches pass through at the cost of 0.2 opacity for app + // compatibility reasons. More details on b/218777508. + Slog.w(TAG, String.format( + "App %s has a system alert window (type = %d) with FLAG_NOT_TOUCHABLE and " + + "LayoutParams.alpha = %.2f > %.2f, setting alpha to %.2f to " + + "let touches pass through (if this is isn't desirable, remove " + + "flag FLAG_NOT_TOUCHABLE).", + attrs.packageName, attrs.type, attrs.alpha, maxOpacity, maxOpacity)); + attrs.alpha = maxOpacity; + win.mWinAnimator.mAlpha = maxOpacity; + } + } + // Check if alternate bars positions were updated. if (mStatusBarAlt == win) { mStatusBarAltPosition = getAltBarPosition(attrs); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 3786761447b3a..5d64ca6c18412 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -778,6 +778,9 @@ public class WindowManagerService extends IWindowManager.Stub private final DisplayHashController mDisplayHashController; + volatile float mMaximumObscuringOpacityForTouch = + InputManager.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH; + @VisibleForTesting final WindowContextListenerController mWindowContextListenerController = new WindowContextListenerController(); @@ -810,6 +813,8 @@ public class WindowManagerService extends IWindowManager.Stub DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR); private final Uri mDisplaySettingsPathUri = Settings.Global.getUriFor( DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH); + private final Uri mMaximumObscuringOpacityForTouchUri = Settings.Global.getUriFor( + Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH); public SettingsObserver() { super(new Handler()); @@ -836,6 +841,8 @@ public class WindowManagerService extends IWindowManager.Stub UserHandle.USER_ALL); resolver.registerContentObserver(mDisplaySettingsPathUri, false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(mMaximumObscuringOpacityForTouchUri, false, this, + UserHandle.USER_ALL); } @Override @@ -884,6 +891,11 @@ public class WindowManagerService extends IWindowManager.Stub return; } + if (mMaximumObscuringOpacityForTouchUri.equals(uri)) { + updateMaximumObscuringOpacityForTouch(); + return; + } + @UpdateAnimationScaleMode final int mode; if (mWindowAnimationScaleUri.equals(uri)) { @@ -903,6 +915,14 @@ public class WindowManagerService extends IWindowManager.Stub void loadSettings() { updateSystemUiSettings(false /* handleChange */); updatePointerLocation(); + updateMaximumObscuringOpacityForTouch(); + } + + void updateMaximumObscuringOpacityForTouch() { + ContentResolver resolver = mContext.getContentResolver(); + mMaximumObscuringOpacityForTouch = Settings.Global.getFloat(resolver, + Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH, + InputManager.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH); } void updateSystemUiSettings(boolean handleChange) {