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

Commit ed652bd1 authored by Candice Lo's avatar Candice Lo
Browse files

(refactor) Move non-UI related components out of MagnifiedViewport

Keep the border drawing related methods and fields in the
MagnifiedViewport, and move the other logics like computing the
magnified region to DisplayMagnifier.

Bug: 291891390
Test: atest frameworks/base/services/tests/servicestests/src/com/android/server/accessibility/magnification
Flag: N/A
Change-Id: Ie629ca85dc17886e254e46afe787422d4b4fa7f2
parent a4ca0a81
Loading
Loading
Loading
Loading
+216 −213
Original line number Diff line number Diff line
@@ -532,7 +532,6 @@ final class AccessibilityController {
        final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
        if (displayMagnifier != null) {
            displayMagnifier.setFullscreenMagnificationActivated(activated);
            displayMagnifier.showMagnificationBoundsIfNeeded();
        }
    }

@@ -626,9 +625,20 @@ final class AccessibilityController {
        private final long mLongAnimationDuration;

        private boolean mIsFullscreenMagnificationActivated = false;
        private final Region mMagnificationRegion = new Region();
        private final Region mOldMagnificationRegion = new Region();

        private final MagnificationSpec mMagnificationSpec = new MagnificationSpec();

        // Following fields are used for computing magnification region
        private final Path mCircularPath;
        private int mTempLayer = 0;
        private final Point mScreenSize = new Point();
        private final SparseArray<WindowState> mTempWindowStates =
                new SparseArray<WindowState>();
        private final RectF mTempRectF = new RectF();
        private final Matrix mTempMatrix = new Matrix();

        DisplayMagnifier(WindowManagerService windowManagerService,
                DisplayContent displayContent,
                Display display,
@@ -644,6 +654,15 @@ final class AccessibilityController {
                    AccessibilityController.getAccessibilityControllerInternal(mService);
            mLongAnimationDuration = mDisplayContext.getResources().getInteger(
                    com.android.internal.R.integer.config_longAnimTime);
            if (mDisplayContext.getResources().getConfiguration().isScreenRound()) {
                mCircularPath = new Path();

                getDisplaySizeLocked(mScreenSize);
                final int centerXY = mScreenSize.x / 2;
                mCircularPath.addCircle(centerXY, centerXY, centerXY, Path.Direction.CW);
            } else {
                mCircularPath = null;
            }
            if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
                mAccessibilityTracing.logTrace(LOG_TAG + ".DisplayMagnifier.constructor",
                        FLAGS_MAGNIFICATION_CALLBACK,
@@ -651,6 +670,7 @@ final class AccessibilityController {
                                + displayContent + "}; display={" + display + "}; callbacks={"
                                + callbacks + "}");
            }
            recomputeBounds();
        }

        void setMagnificationSpec(MagnificationSpec spec) {
@@ -659,7 +679,7 @@ final class AccessibilityController {
                        FLAGS_MAGNIFICATION_CALLBACK, "spec={" + spec + "}");
            }
            updateMagnificationSpec(spec);
            mMagnifedViewport.recomputeBounds();
            recomputeBounds();

            mService.applyMagnificationSpecLocked(mDisplay.getDisplayId(), spec);
            mService.scheduleAnimationLocked();
@@ -671,13 +691,8 @@ final class AccessibilityController {
            } else {
                mMagnificationSpec.clear();
            }
            // If this message is pending we are in a rotation animation and do not want
            // to show the border. We will do so when the pending message is handled.
            if (!mHandler.hasMessages(
                    MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)) {
                mMagnifedViewport.setMagnifiedRegionBorderShown(
                        isFullscreenMagnificationActivated(), true);
            }

            mMagnifedViewport.setShowMagnifiedBorderIfNeeded();
        }

        void setFullscreenMagnificationActivated(boolean activated) {
@@ -687,6 +702,7 @@ final class AccessibilityController {
            }
            mIsFullscreenMagnificationActivated = activated;
            mMagnifedViewport.setMagnifiedRegionBorderShown(activated, true);
            mMagnifedViewport.showMagnificationBoundsIfNeeded();
        }

        boolean isFullscreenMagnificationActivated() {
@@ -705,7 +721,7 @@ final class AccessibilityController {
            if (DEBUG_LAYERS) {
                Slog.i(LOG_TAG, "Layers changed.");
            }
            mMagnifedViewport.recomputeBounds();
            recomputeBounds();
            mService.scheduleAnimationLocked();
        }

@@ -719,6 +735,8 @@ final class AccessibilityController {
                Slog.i(LOG_TAG, "Rotation: " + Surface.rotationToString(rotation)
                        + " displayId: " + displayContent.getDisplayId());
            }

            recomputeBounds();
            mMagnifedViewport.onDisplaySizeChanged();
            mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_DISPLAY_SIZE_CHANGED);
        }
@@ -836,9 +854,7 @@ final class AccessibilityController {
        }

        void getMagnifiedFrameInContentCoords(Rect rect) {
            Region magnificationRegion = new Region();
            mMagnifedViewport.getMagnificationRegion(magnificationRegion);
            magnificationRegion.getBounds(rect);
            mMagnificationRegion.getBounds(rect);
            rect.offset((int) -mMagnificationSpec.offsetX, (int) -mMagnificationSpec.offsetY);
            rect.scale(1.0f / mMagnificationSpec.scale);
        }
@@ -873,8 +889,8 @@ final class AccessibilityController {
                        "outMagnificationRegion={" + outMagnificationRegion + "}");
            }
            // Make sure we're working with the most current bounds
            mMagnifedViewport.recomputeBounds();
            mMagnifedViewport.getMagnificationRegion(outMagnificationRegion);
            recomputeBounds();
            outMagnificationRegion.set(mMagnificationRegion);
        }

        boolean isMagnifying() {
@@ -888,16 +904,6 @@ final class AccessibilityController {
            mMagnifedViewport.destroyWindow();
        }

        // Can be called outside of a surface transaction
        void showMagnificationBoundsIfNeeded() {
            if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
                mAccessibilityTracing.logTrace(LOG_TAG + ".showMagnificationBoundsIfNeeded",
                        FLAGS_MAGNIFICATION_CALLBACK);
            }
            mHandler.obtainMessage(MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)
                    .sendToTarget();
        }

        void drawMagnifiedRegionBorderIfNeeded() {
            if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
                mAccessibilityTracing.logTrace(LOG_TAG + ".drawMagnifiedRegionBorderIfNeeded",
@@ -906,59 +912,6 @@ final class AccessibilityController {
            mMagnifedViewport.drawWindowIfNeeded();
        }

        void dump(PrintWriter pw, String prefix) {
            mMagnifedViewport.dump(pw, prefix);
        }

        private final class MagnifiedViewport {

            private final SparseArray<WindowState> mTempWindowStates =
                    new SparseArray<WindowState>();

            private final RectF mTempRectF = new RectF();

            private final Point mScreenSize = new Point();

            private final Matrix mTempMatrix = new Matrix();

            private final Region mMagnificationRegion = new Region();
            private final Region mOldMagnificationRegion = new Region();

            private final Path mCircularPath;

            private final float mBorderWidth;
            private final int mHalfBorderWidth;
            private final int mDrawBorderInset;

            private final ViewportWindow mWindow;

            private boolean mFullRedrawNeeded;
            private int mTempLayer = 0;

            MagnifiedViewport() {
                mBorderWidth = mDisplayContext.getResources().getDimension(
                        com.android.internal.R.dimen.accessibility_magnification_indicator_width);
                mHalfBorderWidth = (int) Math.ceil(mBorderWidth / 2);
                mDrawBorderInset = (int) mBorderWidth / 2;
                mWindow = new ViewportWindow(mDisplayContext);

                if (mDisplayContext.getResources().getConfiguration().isScreenRound()) {
                    mCircularPath = new Path();

                    getDisplaySizeLocked(mScreenSize);
                    final int centerXY = mScreenSize.x / 2;
                    mCircularPath.addCircle(centerXY, centerXY, centerXY, Path.Direction.CW);
                } else {
                    mCircularPath = null;
                }

                recomputeBounds();
            }

            void getMagnificationRegion(@NonNull Region outMagnificationRegion) {
                outMagnificationRegion.set(mMagnificationRegion);
            }

        void recomputeBounds() {
            getDisplaySizeLocked(mScreenSize);
            final int screenWidth = mScreenSize.x;
@@ -1053,28 +1006,13 @@ final class AccessibilityController {
            }
            visibleWindows.clear();

                mMagnificationRegion.op(mDrawBorderInset, mDrawBorderInset,
                        screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset,
                        Region.Op.INTERSECT);
            mMagnifedViewport.intersectWithDrawBorderInset(screenWidth, screenHeight);


            final boolean magnifiedChanged =
                    !mOldMagnificationRegion.equals(mMagnificationRegion);
            if (magnifiedChanged) {
                    mWindow.setBounds(mMagnificationRegion);
                    final Rect dirtyRect = mTempRect1;
                    if (mFullRedrawNeeded) {
                        mFullRedrawNeeded = false;
                        dirtyRect.set(mDrawBorderInset, mDrawBorderInset,
                                screenWidth - mDrawBorderInset,
                                screenHeight - mDrawBorderInset);
                        mWindow.invalidate(dirtyRect);
                    } else {
                        final Region dirtyRegion = mTempRegion3;
                        dirtyRegion.set(mMagnificationRegion);
                        dirtyRegion.op(mOldMagnificationRegion, Region.Op.XOR);
                        dirtyRegion.getBounds(dirtyRect);
                        mWindow.invalidate(dirtyRect);
                    }
                mMagnifedViewport.updateBorderDrawingStatus(screenWidth, screenHeight);

                mOldMagnificationRegion.set(mMagnificationRegion);
                final SomeArgs args = SomeArgs.obtain();
@@ -1114,6 +1052,89 @@ final class AccessibilityController {
                    || windowType == TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
        }

        private void populateWindowsOnScreen(SparseArray<WindowState> outWindows) {
            mTempLayer = 0;
            mDisplayContent.forAllWindows((w) -> {
                if (w.isOnScreen() && w.isVisible()
                        && (w.mAttrs.alpha != 0)) {
                    mTempLayer++;
                    outWindows.put(mTempLayer, w);
                }
            }, /* traverseTopToBottom= */ false);
        }

        private void getDisplaySizeLocked(Point outSize) {
            final Rect bounds =
                    mDisplayContent.getConfiguration().windowConfiguration.getBounds();
            outSize.set(bounds.width(), bounds.height());
        }

        void dump(PrintWriter pw, String prefix) {
            mMagnifedViewport.dump(pw, prefix);
        }

        private final class MagnifiedViewport {

            private final float mBorderWidth;
            private final int mHalfBorderWidth;
            private final int mDrawBorderInset;

            private final ViewportWindow mWindow;

            private boolean mFullRedrawNeeded;

            MagnifiedViewport() {
                mBorderWidth = mDisplayContext.getResources().getDimension(
                        com.android.internal.R.dimen.accessibility_magnification_indicator_width);
                mHalfBorderWidth = (int) Math.ceil(mBorderWidth / 2);
                mDrawBorderInset = (int) mBorderWidth / 2;
                mWindow = new ViewportWindow(mDisplayContext);
            }

            void updateBorderDrawingStatus(int screenWidth, int screenHeight) {
                mWindow.setBounds(mMagnificationRegion);
                final Rect dirtyRect = mTempRect1;
                if (mFullRedrawNeeded) {
                    mFullRedrawNeeded = false;
                    dirtyRect.set(mDrawBorderInset, mDrawBorderInset,
                            screenWidth - mDrawBorderInset,
                            screenHeight - mDrawBorderInset);
                    mWindow.invalidate(dirtyRect);
                } else {
                    final Region dirtyRegion = mTempRegion3;
                    dirtyRegion.set(mMagnificationRegion);
                    dirtyRegion.op(mOldMagnificationRegion, Region.Op.XOR);
                    dirtyRegion.getBounds(dirtyRect);
                    mWindow.invalidate(dirtyRect);
                }
            }

            void setShowMagnifiedBorderIfNeeded() {
                // If this message is pending, we are in a rotation animation and do not want
                // to show the border. We will do so when the pending message is handled.
                if (!mHandler.hasMessages(
                        MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)) {
                    setMagnifiedRegionBorderShown(
                            isFullscreenMagnificationActivated(), true);
                }
            }

            // Can be called outside of a surface transaction
            void showMagnificationBoundsIfNeeded() {
                if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
                    mAccessibilityTracing.logTrace(LOG_TAG + ".showMagnificationBoundsIfNeeded",
                            FLAGS_MAGNIFICATION_CALLBACK);
                }
                mHandler.obtainMessage(MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)
                        .sendToTarget();
            }

            void intersectWithDrawBorderInset(int screenWidth, int screenHeight) {
                mMagnificationRegion.op(mDrawBorderInset, mDrawBorderInset,
                        screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset,
                        Region.Op.INTERSECT);
            }

            void onDisplaySizeChanged() {
                // If fullscreen magnification is activated, hide the border immediately so
                // the user does not see strange artifacts during display size changed caused by
@@ -1128,7 +1149,6 @@ final class AccessibilityController {
                            MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED);
                    mHandler.sendMessageDelayed(message, delay);
                }
                recomputeBounds();
                mWindow.updateSize();
            }

@@ -1149,23 +1169,6 @@ final class AccessibilityController {
                mWindow.releaseSurface();
            }

            private void populateWindowsOnScreen(SparseArray<WindowState> outWindows) {
                mTempLayer = 0;
                mDisplayContent.forAllWindows((w) -> {
                    if (w.isOnScreen() && w.isVisible()
                            && (w.mAttrs.alpha != 0)) {
                        mTempLayer++;
                        outWindows.put(mTempLayer, w);
                    }
                }, false /* traverseTopToBottom */ );
            }

            private void getDisplaySizeLocked(Point outSize) {
                final Rect bounds =
                        mDisplayContent.getConfiguration().windowConfiguration.getBounds();
                outSize.set(bounds.width(), bounds.height());
            }

            void dump(PrintWriter pw, String prefix) {
                mWindow.dump(pw, prefix);
            }