Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 213dd25e authored by Qinchen Gu's avatar Qinchen Gu
Browse files

Set view bounds in parent by diff'ing the bounds in screen with parent.

The getBoundsInParent() has been deprecated, the getBoundsInScreen() is the recommended alternative for this. The Jetpack compose only sets the boundary via setBoundsInScreen() (given it's the new API), thus the getBoundsInParent() is always returning 0. Literally the bounding boxes of the AssistStructure are broken with Jetpack compose.

Now update the code to use the recommended alternatives.

Flag: android.view.flags.calculate_bounds_in_parent_from_bounds_in_screen
Bug: 366131857
Test: atest CtsAutoFillServiceTestCases
      dump Assist Structure view hierarchy and check for bounds.
Change-Id: I78717c5d2faff06b9303adcfd8af1c8eeddf11fe
parent 88d3e14f
Loading
Loading
Loading
Loading
+41 −4
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_H
import static android.view.flags.Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API;
import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API;
import static android.view.flags.Flags.calculateBoundsInParentFromBoundsInScreen;
import static android.view.flags.Flags.enableUseMeasureCacheDuringForceLayout;
import static android.view.flags.Flags.sensitiveContentAppProtection;
import static android.view.flags.Flags.toolkitFrameRateAnimationBugfix25q1;
@@ -966,6 +967,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    private static boolean sAlwaysRemeasureExactly = false;
    /**
     * When true calculates the bounds in parent from bounds in screen relative to its parents.
     * This addresses the deprecated API (setBoundsInParent) in Compose, which causes empty
     * getBoundsInParent call for Compose apps.
     */
    private static boolean sCalculateBoundsInParentFromBoundsInScreenFlagValue = false;
    /**
     * When true makes it possible to use onMeasure caches also when the force layout flag is
     * enabled. This helps avoiding multiple measures in the same frame with the same dimensions.
@@ -2556,6 +2564,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        sToolkitSetFrameRateReadOnlyFlagValue = toolkitSetFrameRateReadOnly();
        sToolkitMetricsForFrameRateDecisionFlagValue = toolkitMetricsForFrameRateDecision();
        sCalculateBoundsInParentFromBoundsInScreenFlagValue =
                calculateBoundsInParentFromBoundsInScreen();
        sUseMeasureCacheDuringForceLayoutFlagValue = enableUseMeasureCacheDuringForceLayout();
    }
@@ -9776,7 +9786,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            structure.setChildCount(1);
            final ViewStructure root = structure.newChild(0);
            if (info != null) {
                populateVirtualStructure(root, provider, info, forAutofill);
                populateVirtualStructure(root, provider, info, null, forAutofill);
                info.recycle();
            } else {
                Log.w(AUTOFILL_LOG_TAG, "AccessibilityNodeInfo is null.");
@@ -11075,11 +11085,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    private void populateVirtualStructure(ViewStructure structure,
            AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
            boolean forAutofill) {
            @Nullable AccessibilityNodeInfo parentInfo, boolean forAutofill) {
        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
                null, null, info.getViewIdResourceName());
        Rect rect = structure.getTempRect();
        // The bounds in parent for Jetpack Compose views aren't set as setBoundsInParent is
        // deprecated, and only setBoundsInScreen is called.
        // The bounds in parent can be calculated by diff'ing the child view's bounds in screen with
        // the parent's.
        if (sCalculateBoundsInParentFromBoundsInScreenFlagValue) {
            getBoundsInParent(info, parentInfo, rect);
        } else {
            info.getBoundsInParent(rect);
        }
        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
        structure.setVisibility(VISIBLE);
        structure.setEnabled(info.isEnabled());
@@ -11163,13 +11181,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
                if (cinfo != null) {
                    ViewStructure child = structure.newChild(i);
                    populateVirtualStructure(child, provider, cinfo, forAutofill);
                    populateVirtualStructure(child, provider, cinfo, info, forAutofill);
                    cinfo.recycle();
                }
            }
        }
    }
    private void getBoundsInParent(@NonNull AccessibilityNodeInfo info,
            @Nullable AccessibilityNodeInfo parentInfo, @NonNull Rect rect) {
        info.getBoundsInParent(rect);
        // Fallback to calculate bounds in parent by diffing the bounds in
        // screen if it's all 0.
        if ((rect.left | rect.top | rect.right | rect.bottom) == 0) {
            if (parentInfo != null) {
                Rect parentBoundsInScreen = parentInfo.getBoundsInScreen();
                Rect boundsInScreen = info.getBoundsInScreen();
                rect.set(boundsInScreen.left - parentBoundsInScreen.left,
                        boundsInScreen.top - parentBoundsInScreen.top,
                        boundsInScreen.right - parentBoundsInScreen.left,
                        boundsInScreen.bottom - parentBoundsInScreen.top);
            } else {
                info.getBoundsInScreen(rect);
            }
        }
    }
    /**
     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
     * implementation calls {@link #onProvideStructure} and