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

Commit 004167a6 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

PointerLocationView: Reland optimization for trace drawing

First attempt:
commit I6a5c5953ef80537e7066396e085cb15ad67f33b7

We now resize the trace bitmap whenever the display size changes.

Bug: 283195699
Flag: EXEMPT bug fix
Test: manual, enable pointer location
Change-Id: I47a3d668e212e01c4e911b771980ad839e78499c
parent e0f4589f
Loading
Loading
Loading
Loading
+76 −60
Original line number Diff line number Diff line
@@ -16,14 +16,19 @@

package com.android.internal.widget;

import static java.lang.Float.NaN;

import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.RectF;
import android.graphics.Region;
import android.hardware.input.InputManager;
@@ -65,11 +70,14 @@ public class PointerLocationView extends View implements InputDeviceListener,
    private static final PointerState EMPTY_POINTER_STATE = new PointerState();

    public static class PointerState {
        // Trace of previous points.
        private float[] mTraceX = new float[32];
        private float[] mTraceY = new float[32];
        private boolean[] mTraceCurrent = new boolean[32];
        private int mTraceCount;
        private float mCurrentX = NaN;
        private float mCurrentY = NaN;
        private float mPreviousX = NaN;
        private float mPreviousY = NaN;
        private float mFirstX = NaN;
        private float mFirstY = NaN;
        private boolean mPreviousPointIsHistorical;
        private boolean mCurrentPointIsHistorical;

        // True if the pointer is down.
        @UnsupportedAppUsage
@@ -96,31 +104,20 @@ public class PointerLocationView extends View implements InputDeviceListener,
        public PointerState() {
        }

        public void clearTrace() {
            mTraceCount = 0;
        void addTrace(float x, float y, boolean isHistorical) {
            if (Float.isNaN(mFirstX)) {
                mFirstX = x;
            }

        public void addTrace(float x, float y, boolean current) {
            int traceCapacity = mTraceX.length;
            if (mTraceCount == traceCapacity) {
                traceCapacity *= 2;
                float[] newTraceX = new float[traceCapacity];
                System.arraycopy(mTraceX, 0, newTraceX, 0, mTraceCount);
                mTraceX = newTraceX;

                float[] newTraceY = new float[traceCapacity];
                System.arraycopy(mTraceY, 0, newTraceY, 0, mTraceCount);
                mTraceY = newTraceY;

                boolean[] newTraceCurrent = new boolean[traceCapacity];
                System.arraycopy(mTraceCurrent, 0, newTraceCurrent, 0, mTraceCount);
                mTraceCurrent = newTraceCurrent;
            if (Float.isNaN(mFirstY)) {
                mFirstY = y;
            }

            mTraceX[mTraceCount] = x;
            mTraceY[mTraceCount] = y;
            mTraceCurrent[mTraceCount] = current;
            mTraceCount += 1;
            mPreviousX = mCurrentX;
            mPreviousY = mCurrentY;
            mCurrentX = x;
            mCurrentY = y;
            mPreviousPointIsHistorical = mCurrentPointIsHistorical;
            mCurrentPointIsHistorical = isHistorical;
        }
    }

@@ -149,6 +146,12 @@ public class PointerLocationView extends View implements InputDeviceListener,
    private final SparseArray<PointerState> mPointers = new SparseArray<PointerState>();
    private final PointerCoords mTempCoords = new PointerCoords();

    // Draw the trace of all pointers in the current gesture in a separate layer
    // that is not cleared on every frame so that we don't have to re-draw the
    // entire trace on each frame.
    private Bitmap mTraceBitmap;
    private final Canvas mTraceCanvas;

    private final Region mSystemGestureExclusion = new Region();
    private final Region mSystemGestureExclusionRejected = new Region();
    private final Path mSystemGestureExclusionPath = new Path();
@@ -197,6 +200,9 @@ public class PointerLocationView extends View implements InputDeviceListener,
        mPathPaint.setARGB(255, 0, 96, 255);
        mPathPaint.setStyle(Paint.Style.STROKE);

        mTraceCanvas = new Canvas();
        configureTraceBitmap();

        configureDensityDependentFactors();

        mSystemGestureExclusionPaint = new Paint();
@@ -286,6 +292,8 @@ public class PointerLocationView extends View implements InputDeviceListener,
    protected void onDraw(Canvas canvas) {
        final int NP = mPointers.size();

        canvas.drawBitmap(mTraceBitmap, 0, 0, null);

        if (!mSystemGestureExclusion.isEmpty()) {
            mSystemGestureExclusionPath.reset();
            mSystemGestureExclusion.getBoundaryPath(mSystemGestureExclusionPath);
@@ -304,32 +312,9 @@ public class PointerLocationView extends View implements InputDeviceListener,
        // Pointer trace.
        for (int p = 0; p < NP; p++) {
            final PointerState ps = mPointers.valueAt(p);
            float lastX = ps.mCurrentX, lastY = ps.mCurrentY;

            // Draw path.
            final int N = ps.mTraceCount;
            float lastX = 0, lastY = 0;
            boolean haveLast = false;
            boolean drawn = false;
            mPaint.setARGB(255, 128, 255, 255);
            for (int i = 0; i < N; i++) {
                float x = ps.mTraceX[i];
                float y = ps.mTraceY[i];
                if (Float.isNaN(x) || Float.isNaN(y)) {
                    haveLast = false;
                    continue;
                }
                if (haveLast) {
                    canvas.drawLine(lastX, lastY, x, y, mPathPaint);
                    final Paint paint = ps.mTraceCurrent[i - 1] ? mCurrentPointPaint : mPaint;
                    canvas.drawPoint(lastX, lastY, paint);
                    drawn = true;
                }
                lastX = x;
                lastY = y;
                haveLast = true;
            }

            if (drawn) {
            if (!Float.isNaN(lastX) && !Float.isNaN(lastY)) {
                // Draw velocity vector.
                mPaint.setARGB(255, 255, 64, 128);
                float xVel = ps.mXVelocity * (1000 / 60);
@@ -425,8 +410,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
                .append(" / ").append(mMaxNumPointers)
                .toString(), 1, base, mTextPaint);

        final int count = ps.mTraceCount;
        if ((mCurDown && ps.mCurDown) || count == 0) {
        if ((mCurDown && ps.mCurDown) || Float.isNaN(ps.mCurrentX)) {
            canvas.drawRect(itemW, mHeaderPaddingTop, (itemW * 2) - 1, bottom,
                    mTextBackgroundPaint);
            canvas.drawText(mText.clear()
@@ -438,8 +422,8 @@ public class PointerLocationView extends View implements InputDeviceListener,
                    .append("Y: ").append(ps.mCoords.y, 1)
                    .toString(), 1 + itemW * 2, base, mTextPaint);
        } else {
            float dx = ps.mTraceX[count - 1] - ps.mTraceX[0];
            float dy = ps.mTraceY[count - 1] - ps.mTraceY[0];
            float dx = ps.mCurrentX - ps.mFirstX;
            float dy = ps.mCurrentY - ps.mFirstY;
            canvas.drawRect(itemW, mHeaderPaddingTop, (itemW * 2) - 1, bottom,
                    Math.abs(dx) < mVC.getScaledTouchSlop()
                            ? mTextBackgroundPaint : mTextLevelPaint);
@@ -599,6 +583,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
                mCurNumPointers = 0;
                mMaxNumPointers = 0;
                mVelocity.clear();
                mTraceCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                if (mAltVelocity != null) {
                    mAltVelocity.clear();
                }
@@ -647,7 +632,8 @@ public class PointerLocationView extends View implements InputDeviceListener,
                    logCoords("Pointer", action, i, coords, id, event);
                }
                if (ps != null) {
                    ps.addTrace(coords.x, coords.y, false);
                    ps.addTrace(coords.x, coords.y, /*isHistorical*/ true);
                    updateDrawTrace(ps);
                }
            }
        }
@@ -660,7 +646,8 @@ public class PointerLocationView extends View implements InputDeviceListener,
                logCoords("Pointer", action, i, coords, id, event);
            }
            if (ps != null) {
                ps.addTrace(coords.x, coords.y, true);
                ps.addTrace(coords.x, coords.y, /*isHistorical*/ false);
                updateDrawTrace(ps);
                ps.mXVelocity = mVelocity.getXVelocity(id);
                ps.mYVelocity = mVelocity.getYVelocity(id);
                if (mAltVelocity != null) {
@@ -703,13 +690,26 @@ public class PointerLocationView extends View implements InputDeviceListener,
                if (mActivePointerId == id) {
                    mActivePointerId = event.getPointerId(index == 0 ? 1 : 0);
                }
                ps.addTrace(Float.NaN, Float.NaN, false);
                ps.addTrace(Float.NaN, Float.NaN, true);
            }
        }

        invalidate();
    }

    private void updateDrawTrace(PointerState ps) {
        mPaint.setARGB(255, 128, 255, 255);
        float x = ps.mCurrentX;
        float y = ps.mCurrentY;
        float lastX = ps.mPreviousX;
        float lastY = ps.mPreviousY;
        if (!Float.isNaN(x) && !Float.isNaN(y) && !Float.isNaN(lastX) && !Float.isNaN(lastY)) {
            mTraceCanvas.drawLine(lastX, lastY, x, y, mPathPaint);
            Paint paint = ps.mPreviousPointIsHistorical ? mPaint : mCurrentPointPaint;
            mTraceCanvas.drawPoint(lastX, lastY, paint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        onPointerEvent(event);
@@ -999,6 +999,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        configureTraceBitmap();
        configureDensityDependentFactors();
    }

@@ -1010,4 +1011,19 @@ public class PointerLocationView extends View implements InputDeviceListener,
        mCurrentPointPaint.setStrokeWidth(1 * mDensity);
        mPathPaint.setStrokeWidth(1 * mDensity);
    }

    private void configureTraceBitmap() {
        final int width = mContext.getDisplay().getWidth();
        final int height = mContext.getDisplay().getHeight();
        if (mTraceBitmap != null && mTraceBitmap.getWidth() == width
                && mTraceBitmap.getHeight() == height) {
            return;
        }
        if (width <= 0 || height <= 0) {
            Slog.w(TAG, "Ignoring configuration: invalid display size: " + width + "x" + height);
            return;
        }
        mTraceBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        mTraceCanvas.setBitmap(mTraceBitmap);
    }
}