From fa486cd2283cca0a57a783bc6bdf73e08fa04e84 Mon Sep 17 00:00:00 2001 From: ryanlwlin Date: Thu, 7 Oct 2021 20:24:45 +0800 Subject: [PATCH] Do NOT MERGE Fix magnification border includes taskbar The window type of the Taskbar is navigation_bar_paenel, which is unmagnifiable. However, we used to exclude these windows from magnification region computation to avoid cutout. When the foldables is unfolded, the taskbar wouldn't cause the cutout. To fix this problem, so we add a flag to distinguish the windows that cause the cutout. Bug: 196510717 Test: manual test Change-Id: Ibbc9c51ead9ea492f1f2e598587b21dd28d30a2b --- core/java/android/view/WindowManager.java | 19 +++++++++++++++ .../AccessibilityFloatingMenuView.java | 2 ++ .../server/wm/AccessibilityController.java | 8 +++---- .../AccessibilityManagerServiceTest.java | 23 ++++++++++++------- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 51cd95e427428..8764ccc9d5f86 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -2440,6 +2440,20 @@ public interface WindowManager extends ViewManager { */ public static final int PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY = 0x00100000; + /** + * Flag to indicate that this window will be excluded while computing the magnifiable region + * on the un-scaled screen coordinate, which could avoid the cutout on the magnification + * border. It should be used for unmagnifiable overlays. + * + *

+ * Note unlike {@link #PRIVATE_FLAG_NOT_MAGNIFIABLE}, this flag doesn't affect the ability + * of magnification. If you want to the window to be unmagnifiable and doesn't lead to the + * cutout, you need to combine both of them. + *

+ * @hide + */ + public static final int PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION = 0x00200000; + /** * Flag to prevent the window from being magnified by the accessibility magnifier. * @@ -2551,6 +2565,7 @@ public interface WindowManager extends ViewManager { PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE, SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, + PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION, PRIVATE_FLAG_NOT_MAGNIFIABLE, PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC, @@ -2631,6 +2646,10 @@ public interface WindowManager extends ViewManager { mask = PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, equals = PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, name = "IS_ROUNDED_CORNERS_OVERLAY"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION, + equals = PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION, + name = "EXCLUDE_FROM_SCREEN_MAGNIFICATION"), @ViewDebug.FlagToString( mask = PRIVATE_FLAG_NOT_MAGNIFIABLE, equals = PRIVATE_FLAG_NOT_MAGNIFIABLE, diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java index 59d9aff2ef460..d2703f5e73a2d 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java @@ -22,6 +22,7 @@ import static android.util.MathUtils.sq; import static android.view.WindowInsets.Type.displayCutout; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.systemBars; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION; import static java.util.Objects.requireNonNull; @@ -659,6 +660,7 @@ public class AccessibilityFloatingMenuView extends FrameLayout | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, PixelFormat.TRANSLUCENT); params.receiveInsetsIgnoringZOrder = true; + params.privateFlags |= PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION; params.windowAnimations = android.R.style.Animation_Translucent; params.gravity = Gravity.START | Gravity.TOP; params.x = (mAlignment == Alignment.RIGHT) ? getMaxWindowX() : getMinWindowX(); diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index cf9783fb92419..38a48570ba16c 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -20,11 +20,11 @@ import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATIO import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK; import static android.os.Build.IS_USER; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; -import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static com.android.server.accessibility.AccessibilityTraceFileProto.ENTRY; import static com.android.server.accessibility.AccessibilityTraceFileProto.MAGIC_NUMBER; @@ -1008,6 +1008,8 @@ final class AccessibilityController { WindowState windowState = visibleWindows.valueAt(i); final int windowType = windowState.mAttrs.type; if (isExcludedWindowType(windowType) + || ((windowState.mAttrs.privateFlags + & PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION) != 0) || ((windowState.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0)) { continue; @@ -1073,7 +1075,6 @@ final class AccessibilityController { } } } - visibleWindows.clear(); mMagnificationRegion.op(mDrawBorderInset, mDrawBorderInset, @@ -1110,9 +1111,6 @@ final class AccessibilityController { private boolean isExcludedWindowType(int windowType) { return windowType == TYPE_MAGNIFICATION_OVERLAY - // Omit the touch region to avoid the cut out of the magnification - // bounds because nav bar panel is unmagnifiable. - || windowType == TYPE_NAVIGATION_BAR_PANEL // Omit the touch region of window magnification to avoid the cut out of the // magnification and the magnified center of window magnification could be // in the bounds diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java index 2a5bb18ae4288..df975cda54a50 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java @@ -40,7 +40,6 @@ import android.graphics.drawable.Icon; import android.os.IBinder; import android.os.UserHandle; import android.provider.Settings; -import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; @@ -54,13 +53,16 @@ import com.android.server.accessibility.test.MessageCapturingHandler; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.WindowManagerInternal; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; /** * APCT tests for {@link AccessibilityManagerService}. */ -public class AccessibilityManagerServiceTest extends AndroidTestCase { +public class AccessibilityManagerServiceTest { private static final String TAG = "A11Y_MANAGER_SERVICE_TEST"; private static final int ACTION_ID = 20; private static final String LABEL = "label"; @@ -104,8 +106,8 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase { private AccessibilityServiceConnection mAccessibilityServiceConnection; private AccessibilityManagerService mA11yms; - @Override - protected void setUp() throws Exception { + @Before + public void setUp() throws Exception { MockitoAnnotations.initMocks(this); LocalServices.removeServiceForTest(WindowManagerInternal.class); LocalServices.removeServiceForTest(ActivityTaskManagerInternal.class); @@ -167,44 +169,48 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase { } @SmallTest + @Test public void testRegisterSystemActionWithoutPermission() throws Exception { doThrow(SecurityException.class).when(mMockSecurityPolicy) .enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY); try { mA11yms.registerSystemAction(TEST_ACTION, ACTION_ID); - fail(); + Assert.fail(); } catch (SecurityException expected) { } verify(mMockSystemActionPerformer, never()).registerSystemAction(ACTION_ID, TEST_ACTION); } @SmallTest + @Test public void testRegisterSystemAction() throws Exception { mA11yms.registerSystemAction(TEST_ACTION, ACTION_ID); verify(mMockSystemActionPerformer).registerSystemAction(ACTION_ID, TEST_ACTION); } - @SmallTest + @Test public void testUnregisterSystemActionWithoutPermission() throws Exception { doThrow(SecurityException.class).when(mMockSecurityPolicy) .enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY); try { mA11yms.unregisterSystemAction(ACTION_ID); - fail(); + Assert.fail(); } catch (SecurityException expected) { } verify(mMockSystemActionPerformer, never()).unregisterSystemAction(ACTION_ID); } @SmallTest + @Test public void testUnregisterSystemAction() throws Exception { mA11yms.unregisterSystemAction(ACTION_ID); verify(mMockSystemActionPerformer).unregisterSystemAction(ACTION_ID); } @SmallTest + @Test public void testOnSystemActionsChanged() throws Exception { setupAccessibilityServiceConnection(); mA11yms.notifySystemActionsChangedLocked(mUserState); @@ -213,6 +219,7 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase { } @SmallTest + @Test public void testOnMagnificationTransitionFailed_capabilitiesIsAll_fallBackToPreviousMode() { final AccessibilityUserState userState = mA11yms.mUserStates.get( mA11yms.getCurrentUserIdLocked()); @@ -223,7 +230,7 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase { mA11yms.onMagnificationTransitionEndedLocked(false); - assertEquals(Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW, + Assert.assertEquals(Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW, userState.getMagnificationModeLocked()); } }