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

Commit b21df801 authored by Svet Ganov's avatar Svet Ganov
Browse files

Magnification bounds not always animated on a looper thread.

In display manigfication mode we are showing a frame around the
magnified region. Showing and hiding this frame is animated. In
some cases the code calling into the display magnifier is not
running on a looper thread which leads to a crash when interacting
with the property animator. Now the animation is explicitly handled
in a dedicated handler that runs on the window manager's handler
looper thread.

bug:15506701

Change-Id: I3fada775c9fac8820599dd31ac80720021c70cb3
parent b730542b
Loading
Loading
Loading
Loading
+66 −34
Original line number Original line Diff line number Diff line
@@ -614,19 +614,15 @@ final class AccessibilityController {
            private final class ViewportWindow {
            private final class ViewportWindow {
                private static final String SURFACE_TITLE = "Magnification Overlay";
                private static final String SURFACE_TITLE = "Magnification Overlay";


                private static final String PROPERTY_NAME_ALPHA = "alpha";

                private static final int MIN_ALPHA = 0;
                private static final int MAX_ALPHA = 255;

                private final Region mBounds = new Region();
                private final Region mBounds = new Region();
                private final Rect mDirtyRect = new Rect();
                private final Rect mDirtyRect = new Rect();
                private final Paint mPaint = new Paint();
                private final Paint mPaint = new Paint();


                private final ValueAnimator mShowHideFrameAnimator;
                private final SurfaceControl mSurfaceControl;
                private final SurfaceControl mSurfaceControl;
                private final Surface mSurface = new Surface();
                private final Surface mSurface = new Surface();


                private final AnimationController mAnimationController;

                private boolean mShown;
                private boolean mShown;
                private int mAlpha;
                private int mAlpha;


@@ -651,6 +647,9 @@ final class AccessibilityController {
                    mSurfaceControl.setPosition(0, 0);
                    mSurfaceControl.setPosition(0, 0);
                    mSurface.copyFrom(mSurfaceControl);
                    mSurface.copyFrom(mSurfaceControl);


                    mAnimationController = new AnimationController(context,
                            mWindowManagerService.mH.getLooper());

                    TypedValue typedValue = new TypedValue();
                    TypedValue typedValue = new TypedValue();
                    context.getTheme().resolveAttribute(R.attr.colorActivatedHighlight,
                    context.getTheme().resolveAttribute(R.attr.colorActivatedHighlight,
                            typedValue, true);
                            typedValue, true);
@@ -660,14 +659,6 @@ final class AccessibilityController {
                    mPaint.setStrokeWidth(mBorderWidth);
                    mPaint.setStrokeWidth(mBorderWidth);
                    mPaint.setColor(borderColor);
                    mPaint.setColor(borderColor);


                    Interpolator interpolator = new DecelerateInterpolator(2.5f);
                    final long longAnimationDuration = context.getResources().getInteger(
                            com.android.internal.R.integer.config_longAnimTime);

                    mShowHideFrameAnimator = ObjectAnimator.ofInt(this, PROPERTY_NAME_ALPHA,
                            MIN_ALPHA, MAX_ALPHA);
                    mShowHideFrameAnimator.setInterpolator(interpolator);
                    mShowHideFrameAnimator.setDuration(longAnimationDuration);
                    mInvalidated = true;
                    mInvalidated = true;
                }
                }


@@ -677,24 +668,7 @@ final class AccessibilityController {
                            return;
                            return;
                        }
                        }
                        mShown = shown;
                        mShown = shown;
                        if (animate) {
                        mAnimationController.onFrameShownStateChanged(shown, animate);
                            if (mShowHideFrameAnimator.isRunning()) {
                                mShowHideFrameAnimator.reverse();
                            } else {
                                if (shown) {
                                    mShowHideFrameAnimator.start();
                                } else {
                                    mShowHideFrameAnimator.reverse();
                                }
                            }
                        } else {
                            mShowHideFrameAnimator.cancel();
                            if (shown) {
                                setAlpha(MAX_ALPHA);
                            } else {
                                setAlpha(MIN_ALPHA);
                            }
                        }
                        if (DEBUG_VIEWPORT_WINDOW) {
                        if (DEBUG_VIEWPORT_WINDOW) {
                            Slog.i(LOG_TAG, "ViewportWindow shown: " + mShown);
                            Slog.i(LOG_TAG, "ViewportWindow shown: " + mShown);
                        }
                        }
@@ -801,6 +775,64 @@ final class AccessibilityController {
                    mSurfaceControl.release();
                    mSurfaceControl.release();
                    mSurface.release();
                    mSurface.release();
                }
                }

                private final class AnimationController extends Handler {
                    private static final String PROPERTY_NAME_ALPHA = "alpha";

                    private static final int MIN_ALPHA = 0;
                    private static final int MAX_ALPHA = 255;

                    private static final int MSG_FRAME_SHOWN_STATE_CHANGED = 1;

                    private final ValueAnimator mShowHideFrameAnimator;

                    public AnimationController(Context context, Looper looper) {
                        super(looper);
                        mShowHideFrameAnimator = ObjectAnimator.ofInt(ViewportWindow.this,
                                PROPERTY_NAME_ALPHA, MIN_ALPHA, MAX_ALPHA);

                        Interpolator interpolator = new DecelerateInterpolator(2.5f);
                        final long longAnimationDuration = context.getResources().getInteger(
                                com.android.internal.R.integer.config_longAnimTime);

                        mShowHideFrameAnimator.setInterpolator(interpolator);
                        mShowHideFrameAnimator.setDuration(longAnimationDuration);
                    }

                    public void onFrameShownStateChanged(boolean shown, boolean animate) {
                        obtainMessage(MSG_FRAME_SHOWN_STATE_CHANGED,
                                shown ? 1 : 0, animate ? 1 : 0).sendToTarget();
                    }

                    @Override
                    public void handleMessage(Message message) {
                        switch (message.what) {
                            case MSG_FRAME_SHOWN_STATE_CHANGED: {
                                final boolean shown = message.arg1 == 1;
                                final boolean animate = message.arg2 == 1;

                                if (animate) {
                                    if (mShowHideFrameAnimator.isRunning()) {
                                        mShowHideFrameAnimator.reverse();
                                    } else {
                                        if (shown) {
                                            mShowHideFrameAnimator.start();
                                        } else {
                                            mShowHideFrameAnimator.reverse();
                                        }
                                    }
                                } else {
                                    mShowHideFrameAnimator.cancel();
                                    if (shown) {
                                        setAlpha(MAX_ALPHA);
                                    } else {
                                        setAlpha(MIN_ALPHA);
                                    }
                                }
                            } break;
                        }
                    }
                }
            }
            }
        }
        }