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

Commit 828907a1 authored by Arthur Hung's avatar Arthur Hung
Browse files

Fix potential stuck when enabled pointer location

Replace ArrayList by SparseArray to track each pointer by pointer id, so
we could avoid generating lots redundant PointerStates if the event has
an unexpected pointer id value (such as 0xFFFFFFFF).

This also fix text size and path width when the density has changed.

Bug: 243548346
Test: enabled pointer location
Change-Id: I0a5b04b3034f02c3b06803a90d9b97561afdd9e0
parent ac5cbb5e
Loading
Loading
Loading
Loading
+37 −34
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.internal.widget;

import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Insets;
import android.graphics.Paint;
@@ -32,6 +33,7 @@ import android.os.RemoteException;
import android.os.SystemProperties;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.view.ISystemGestureExclusionListener;
import android.view.InputDevice;
import android.view.KeyEvent;
@@ -45,8 +47,6 @@ import android.view.WindowInsets;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicyConstants.PointerEventListener;

import java.util.ArrayList;

public class PointerLocationView extends View implements InputDeviceListener,
        PointerEventListener {
    private static final String TAG = "Pointer";
@@ -61,6 +61,9 @@ public class PointerLocationView extends View implements InputDeviceListener,
     */
    private static final String GESTURE_EXCLUSION_PROP = "debug.pointerlocation.showexclusion";

    // In case when it's in first time or no active pointer found, draw the empty state.
    private static final PointerState EMPTY_POINTER_STATE = new PointerState();

    public static class PointerState {
        // Trace of previous points.
        private float[] mTraceX = new float[32];
@@ -149,7 +152,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
    private int mMaxNumPointers;
    private int mActivePointerId;
    @UnsupportedAppUsage
    private final ArrayList<PointerState> mPointers = new ArrayList<PointerState>();
    private final SparseArray<PointerState> mPointers = new SparseArray<PointerState>();
    private final PointerCoords mTempCoords = new PointerCoords();

    private final Region mSystemGestureExclusion = new Region();
@@ -175,8 +178,6 @@ public class PointerLocationView extends View implements InputDeviceListener,
        mVC = ViewConfiguration.get(c);
        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(10
                * getResources().getDisplayMetrics().density);
        mTextPaint.setARGB(255, 0, 0, 0);
        mTextBackgroundPaint = new Paint();
        mTextBackgroundPaint.setAntiAlias(false);
@@ -188,20 +189,19 @@ public class PointerLocationView extends View implements InputDeviceListener,
        mPaint.setAntiAlias(true);
        mPaint.setARGB(255, 255, 255, 255);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        mCurrentPointPaint = new Paint();
        mCurrentPointPaint.setAntiAlias(true);
        mCurrentPointPaint.setARGB(255, 255, 0, 0);
        mCurrentPointPaint.setStyle(Paint.Style.STROKE);
        mCurrentPointPaint.setStrokeWidth(2);
        mTargetPaint = new Paint();
        mTargetPaint.setAntiAlias(false);
        mTargetPaint.setARGB(255, 0, 0, 192);
        mPathPaint = new Paint();
        mPathPaint.setAntiAlias(false);
        mPathPaint.setARGB(255, 0, 96, 255);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(1);
        mPathPaint.setStyle(Paint.Style.STROKE);

        configureDensityDependentFactors();

        mSystemGestureExclusionPaint = new Paint();
        mSystemGestureExclusionPaint.setARGB(25, 255, 0, 0);
@@ -211,8 +211,6 @@ public class PointerLocationView extends View implements InputDeviceListener,
        mSystemGestureExclusionRejectedPaint.setARGB(25, 0, 0, 255);
        mSystemGestureExclusionRejectedPaint.setStyle(Paint.Style.FILL_AND_STROKE);

        PointerState ps = new PointerState();
        mPointers.add(ps);
        mActivePointerId = 0;

        mVelocity = VelocityTracker.obtain();
@@ -308,7 +306,7 @@ public class PointerLocationView extends View implements InputDeviceListener,

        // Pointer trace.
        for (int p = 0; p < NP; p++) {
            final PointerState ps = mPointers.get(p);
            final PointerState ps = mPointers.valueAt(p);

            // Draw path.
            final int N = ps.mTraceCount;
@@ -319,7 +317,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
            for (int i=0; i < N; i++) {
                float x = ps.mTraceX[i];
                float y = ps.mTraceY[i];
                if (Float.isNaN(x)) {
                if (Float.isNaN(x) || Float.isNaN(y)) {
                    haveLast = false;
                    continue;
                }
@@ -418,10 +416,6 @@ public class PointerLocationView extends View implements InputDeviceListener,
    }

    private void drawLabels(Canvas canvas) {
        if (mActivePointerId < 0 || mActivePointerId >= mPointers.size()) {
            return;
        }

        final int w = getWidth() - mWaterfallInsets.left - mWaterfallInsets.right;
        final int itemW = w / 7;
        final int base = mHeaderPaddingTop - mTextMetrics.ascent + 1;
@@ -429,7 +423,7 @@ public class PointerLocationView extends View implements InputDeviceListener,

        canvas.save();
        canvas.translate(mWaterfallInsets.left, 0);
        final PointerState ps = mPointers.get(mActivePointerId);
        final PointerState ps = mPointers.get(mActivePointerId, EMPTY_POINTER_STATE);

        canvas.drawRect(0, mHeaderPaddingTop, itemW - 1, bottom, mTextBackgroundPaint);
        canvas.drawText(mText.clear()
@@ -600,18 +594,13 @@ public class PointerLocationView extends View implements InputDeviceListener,
    @Override
    public void onPointerEvent(MotionEvent event) {
        final int action = event.getAction();
        int NP = mPointers.size();

        if (action == MotionEvent.ACTION_DOWN
                || (action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) {
            final int index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
                    >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; // will be 0 for down
            if (action == MotionEvent.ACTION_DOWN) {
                for (int p=0; p<NP; p++) {
                    final PointerState ps = mPointers.get(p);
                    ps.clearTrace();
                    ps.mCurDown = false;
                }
                mPointers.clear();
                mCurDown = true;
                mCurNumPointers = 0;
                mMaxNumPointers = 0;
@@ -627,18 +616,17 @@ public class PointerLocationView extends View implements InputDeviceListener,
            }

            final int id = event.getPointerId(index);
            while (NP <= id) {
                PointerState ps = new PointerState();
                mPointers.add(ps);
                NP++;
            PointerState ps = mPointers.get(id);
            if (ps == null) {
                ps = new PointerState();
                mPointers.put(id, ps);
            }

            if (mActivePointerId < 0 || mActivePointerId >= NP
            if (!mPointers.contains(mActivePointerId)
                    || !mPointers.get(mActivePointerId).mCurDown) {
                mActivePointerId = id;
            }

            final PointerState ps = mPointers.get(id);
            ps.mCurDown = true;
            InputDevice device = InputDevice.getDevice(event.getDeviceId());
            ps.mHasBoundingBox = device != null &&
@@ -707,13 +695,13 @@ public class PointerLocationView extends View implements InputDeviceListener,
                    >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; // will be 0 for UP

            final int id = event.getPointerId(index);
            if (id >= NP) {
                Slog.wtf(TAG, "Got pointer ID out of bounds: id=" + id + " arraysize="
                        + NP + " pointerindex=" + index
            final PointerState ps = mPointers.get(id);
            if (ps == null) {
                Slog.wtf(TAG, "Could not find pointer id=" + id + " in mPointers map,"
                        + " size=" + mPointers.size() + " pointerindex=" + index
                        + " action=0x" + Integer.toHexString(action));
                return;
            }
            final PointerState ps = mPointers.get(id);
            ps.mCurDown = false;

            if (action == MotionEvent.ACTION_UP
@@ -1016,4 +1004,19 @@ public class PointerLocationView extends View implements InputDeviceListener,
            }
        }
    };

    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        configureDensityDependentFactors();
    }

    // Compute size by display density.
    private void configureDensityDependentFactors() {
        final float density = getResources().getDisplayMetrics().density;
        mTextPaint.setTextSize(10 * density);
        mPaint.setStrokeWidth(1 * density);
        mCurrentPointPaint.setStrokeWidth(1 * density);
        mPathPaint.setStrokeWidth(1 * density);
    }
}