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

Commit 37f700a8 authored by Adam Powell's avatar Adam Powell Committed by Android (Google) Code Review
Browse files

Merge "InputDevice filtering for jumpy screens. Updated ScaleGestureDetector...

Merge "InputDevice filtering for jumpy screens. Updated ScaleGestureDetector for framework deprecations."
parents e58aa0d9 f5bcc6ad
Loading
Loading
Loading
Loading
+50 −44
Original line number Original line Diff line number Diff line
@@ -154,9 +154,8 @@ public class ScaleGestureDetector {
        boolean handled = true;
        boolean handled = true;


        if (!mGestureInProgress) {
        if (!mGestureInProgress) {
            if ((action == MotionEvent.ACTION_POINTER_1_DOWN ||
            switch (action & MotionEvent.ACTION_MASK) {
                    action == MotionEvent.ACTION_POINTER_2_DOWN) &&
            case MotionEvent.ACTION_POINTER_DOWN: {
                    event.getPointerCount() >= 2) {
                // We have a new multi-finger gesture
                // We have a new multi-finger gesture


                // as orientation can change, query the metrics in touch down
                // as orientation can change, query the metrics in touch down
@@ -204,7 +203,11 @@ public class ScaleGestureDetector {
                } else {
                } else {
                    mGestureInProgress = mListener.onScaleBegin(this);
                    mGestureInProgress = mListener.onScaleBegin(this);
                }
                }
            } else if (action == MotionEvent.ACTION_MOVE && mSloppyGesture) {
            }
            break;
            
            case MotionEvent.ACTION_MOVE:
                if (mSloppyGesture) {
                    // Initiate sloppy gestures if we've moved outside of the slop area.
                    // Initiate sloppy gestures if we've moved outside of the slop area.
                    final float edgeSlop = mEdgeSlop;
                    final float edgeSlop = mEdgeSlop;
                    final float rightSlop = mRightSlopEdge;
                    final float rightSlop = mRightSlopEdge;
@@ -232,26 +235,29 @@ public class ScaleGestureDetector {
                        mSloppyGesture = false;
                        mSloppyGesture = false;
                        mGestureInProgress = mListener.onScaleBegin(this);
                        mGestureInProgress = mListener.onScaleBegin(this);
                    }
                    }
            } else if ((action == MotionEvent.ACTION_POINTER_1_UP
                }
                    || action == MotionEvent.ACTION_POINTER_2_UP)
                break;
                    && mSloppyGesture) {
                
            case MotionEvent.ACTION_POINTER_UP:
                if (mSloppyGesture) {
                    // Set focus point to the remaining finger
                    // Set focus point to the remaining finger
                int id = (((action & MotionEvent.ACTION_POINTER_ID_MASK)
                    int id = (((action & MotionEvent.ACTION_POINTER_INDEX_MASK)
                        >> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) ? 1 : 0;
                            >> MotionEvent.ACTION_POINTER_INDEX_SHIFT) == 0) ? 1 : 0;
                    mFocusX = event.getX(id);
                    mFocusX = event.getX(id);
                    mFocusY = event.getY(id);
                    mFocusY = event.getY(id);
                }
                }
                break;
            }
        } else {
        } else {
            // Transform gesture in progress - attempt to handle it
            // Transform gesture in progress - attempt to handle it
            switch (action) {
            switch (action & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_POINTER_1_UP:
                case MotionEvent.ACTION_POINTER_UP:
                case MotionEvent.ACTION_POINTER_2_UP:
                    // Gesture ended
                    // Gesture ended
                    setContext(event);
                    setContext(event);


                    // Set focus point to the remaining finger
                    // Set focus point to the remaining finger
                    int id = (((action & MotionEvent.ACTION_POINTER_ID_MASK)
                    int id = (((action & MotionEvent.ACTION_POINTER_INDEX_MASK)
                            >> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) ? 1 : 0;
                            >> MotionEvent.ACTION_POINTER_INDEX_SHIFT) == 0) ? 1 : 0;
                    mFocusX = event.getX(id);
                    mFocusX = event.getX(id);
                    mFocusY = event.getY(id);
                    mFocusY = event.getY(id);


+5 −0
Original line number Original line Diff line number Diff line
@@ -268,6 +268,11 @@
         data. -->
         data. -->
    <bool name="config_filterTouchEvents">false</bool>
    <bool name="config_filterTouchEvents">false</bool>


    <!-- Enables special filtering code in the framework for raw touch events
         from the touch driver. This code exists for one particular device,
         and should not be enabled for any others. -->
    <bool name="config_filterJumpyTouchEvents">false</bool>
    
    <!-- Component name of the default wallpaper. This will be ImageWallpaper if not 
    <!-- Component name of the default wallpaper. This will be ImageWallpaper if not 
         specified -->
         specified -->
    <string name="default_wallpaper_component">@null</string>
    <string name="default_wallpaper_component">@null</string>
+165 −0
Original line number Original line Diff line number Diff line
@@ -34,6 +34,16 @@ public class InputDevice {
    /** Maximum number of pointers we will track and report. */
    /** Maximum number of pointers we will track and report. */
    static final int MAX_POINTERS = 10;
    static final int MAX_POINTERS = 10;
    
    
    /**
     * Slop distance for jumpy pointer detection.
     * This is in touchscreen coordinates, not pixels or dips.
     */
    private static final int JUMPY_EPSILON = 30;
    
    /** Number of jumpy points to drop for touchscreens that need it. */
    private static final int JUMPY_TRANSITION_DROPS = 3;
    private static final int JUMPY_DROP_LIMIT = 3;
    
    final int id;
    final int id;
    final int classes;
    final int classes;
    final String name;
    final String name;
@@ -85,6 +95,9 @@ public class InputDevice {
        // it repeatedly.
        // it repeatedly.
        final boolean[] mDroppedBadPoint = new boolean[MAX_POINTERS];
        final boolean[] mDroppedBadPoint = new boolean[MAX_POINTERS];


        // Used to count the number of jumpy points dropped.
        private int mJumpyPointsDropped = 0;
        
        // Used to perform averaging of reported coordinates, to smooth
        // Used to perform averaging of reported coordinates, to smooth
        // the data and filter out transients during a release.
        // the data and filter out transients during a release.
        static final int HISTORY_SIZE = 5;
        static final int HISTORY_SIZE = 5;
@@ -232,6 +245,158 @@ public class InputDevice {
            }
            }
        }
        }
        
        
        void dropJumpyPoint(InputDevice dev) {
            final int nextNumPointers = mNextNumPointers;
            final int lastNumPointers = mLastNumPointers;
            final int[] nextData = mNextData;
            final int[] lastData = mLastData;

            if (nextNumPointers != mLastNumPointers) {
                if (DEBUG_HACKS) {
                    Slog.d("InputDevice", "Different pointer count " + lastNumPointers + 
                            " -> " + nextNumPointers);
                    for (int i = 0; i < nextNumPointers; i++) {
                        int ioff = i * MotionEvent.NUM_SAMPLE_DATA;
                        Slog.d("InputDevice", "Pointer " + i + " (" + 
                                mNextData[ioff + MotionEvent.SAMPLE_X] + ", " +
                                mNextData[ioff + MotionEvent.SAMPLE_Y] + ")");
                    }
                }
                
                // Just drop the first few events going from 1 to 2 pointers.
                // They're bad often enough that they're not worth considering.
                if (lastNumPointers == 1 && nextNumPointers == 2
                        && mJumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
                    mNextNumPointers = 1;
                    mJumpyPointsDropped++;
                } else if (lastNumPointers == 2 && nextNumPointers == 1
                        && mJumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
                    // The event when we go from 2 -> 1 tends to be messed up too
                    System.arraycopy(lastData, 0, nextData, 0, 
                            lastNumPointers * MotionEvent.NUM_SAMPLE_DATA);
                    mNextNumPointers = lastNumPointers;
                    mJumpyPointsDropped++;
                    
                    if (DEBUG_HACKS) {
                        for (int i = 0; i < mNextNumPointers; i++) {
                            int ioff = i * MotionEvent.NUM_SAMPLE_DATA;
                            Slog.d("InputDevice", "Pointer " + i + " replaced (" + 
                                    mNextData[ioff + MotionEvent.SAMPLE_X] + ", " +
                                    mNextData[ioff + MotionEvent.SAMPLE_Y] + ")");
                        }
                    }
                } else {
                    mJumpyPointsDropped = 0;
                    
                    if (DEBUG_HACKS) {
                        Slog.d("InputDevice", "Transition - drop limit reset");
                    }
                }
                return;
            }
            
            // A 'jumpy' point is one where the coordinate value for one axis
            // has jumped to the other pointer's location. No need to do anything
            // else if we only have one pointer.
            if (nextNumPointers < 2) {
                return;
            }
            
            int badPointerIndex = -1;
            int badPointerReplaceXWith = 0;
            int badPointerReplaceYWith = 0;
            int badPointerDistance = Integer.MIN_VALUE;
            for (int i = nextNumPointers - 1; i >= 0; i--) {
                boolean dropx = false;
                boolean dropy = false;
                
                // Limit how many times a jumpy point can get dropped.
                if (mJumpyPointsDropped < JUMPY_DROP_LIMIT) {
                    final int ioff = i * MotionEvent.NUM_SAMPLE_DATA;
                    final int x = nextData[ioff + MotionEvent.SAMPLE_X];
                    final int y = nextData[ioff + MotionEvent.SAMPLE_Y];
                    
                    if (DEBUG_HACKS) {
                        Slog.d("InputDevice", "Point " + i + " (" + x + ", " + y + ")");
                    }

                    // Check if a touch point is too close to another's coordinates
                    for (int j = 0; j < nextNumPointers && !dropx && !dropy; j++) {
                        if (j == i) {
                            continue;
                        }

                        final int joff = j * MotionEvent.NUM_SAMPLE_DATA;
                        final int xOther = nextData[joff + MotionEvent.SAMPLE_X];
                        final int yOther = nextData[joff + MotionEvent.SAMPLE_Y];

                        dropx = Math.abs(x - xOther) <= JUMPY_EPSILON;
                        dropy = Math.abs(y - yOther) <= JUMPY_EPSILON;
                    }
                    
                    if (dropx) {
                        int xreplace = lastData[MotionEvent.SAMPLE_X];
                        int yreplace = lastData[MotionEvent.SAMPLE_Y];
                        int distance = Math.abs(yreplace - y);
                        for (int j = 1; j < lastNumPointers; j++) {
                            final int joff = j * MotionEvent.NUM_SAMPLE_DATA;
                            int lasty = lastData[joff + MotionEvent.SAMPLE_Y];   
                            int currDist = Math.abs(lasty - y);
                            if (currDist < distance) {
                                xreplace = lastData[joff + MotionEvent.SAMPLE_X];
                                yreplace = lasty;
                                distance = currDist;
                            }
                        }
                        
                        int badXDelta = Math.abs(xreplace - x);
                        if (badXDelta > badPointerDistance) {
                            badPointerDistance = badXDelta;
                            badPointerIndex = i;
                            badPointerReplaceXWith = xreplace;
                            badPointerReplaceYWith = yreplace;
                        }
                    } else if (dropy) {
                        int xreplace = lastData[MotionEvent.SAMPLE_X];
                        int yreplace = lastData[MotionEvent.SAMPLE_Y];
                        int distance = Math.abs(xreplace - x);
                        for (int j = 1; j < lastNumPointers; j++) {
                            final int joff = j * MotionEvent.NUM_SAMPLE_DATA;
                            int lastx = lastData[joff + MotionEvent.SAMPLE_X];   
                            int currDist = Math.abs(lastx - x);
                            if (currDist < distance) {
                                xreplace = lastx;
                                yreplace = lastData[joff + MotionEvent.SAMPLE_Y];
                                distance = currDist;
                            }
                        }
                        
                        int badYDelta = Math.abs(yreplace - y);
                        if (badYDelta > badPointerDistance) {
                            badPointerDistance = badYDelta;
                            badPointerIndex = i;
                            badPointerReplaceXWith = xreplace;
                            badPointerReplaceYWith = yreplace;
                        }
                    }
                }
            }
            if (badPointerIndex >= 0) {
                if (DEBUG_HACKS) {
                    Slog.d("InputDevice", "Replacing bad pointer " + badPointerIndex +
                            " with (" + badPointerReplaceXWith + ", " + badPointerReplaceYWith +
                            ")");
                }

                final int offset = badPointerIndex * MotionEvent.NUM_SAMPLE_DATA;
                nextData[offset + MotionEvent.SAMPLE_X] = badPointerReplaceXWith;
                nextData[offset + MotionEvent.SAMPLE_Y] = badPointerReplaceYWith;
                mJumpyPointsDropped++;
            } else {
                mJumpyPointsDropped = 0;
            }
        }
        
        /**
        /**
         * Special hack for devices that have bad screen data: aggregate and
         * Special hack for devices that have bad screen data: aggregate and
         * compute averages of the coordinate data, to reduce the amount of
         * compute averages of the coordinate data, to reduce the amount of
+14 −2
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server;


import android.content.Context;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Environment;
import android.os.Environment;
import android.os.LatencyTimer;
import android.os.LatencyTimer;
import android.os.PowerManager;
import android.os.PowerManager;
@@ -60,6 +61,12 @@ public abstract class KeyInputQueue {
     */
     */
    static boolean BAD_TOUCH_HACK = false;
    static boolean BAD_TOUCH_HACK = false;
    
    
    /**
     * Turn on some hacks to improve touch interaction with another device
     * where touch coordinate data can get corrupted.
     */
    static boolean JUMPY_TOUCH_HACK = false;
    
    private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
    private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";


    final SparseArray<InputDevice> mDevices = new SparseArray<InputDevice>();
    final SparseArray<InputDevice> mDevices = new SparseArray<InputDevice>();
@@ -284,8 +291,10 @@ public abstract class KeyInputQueue {
            lt = new LatencyTimer(100, 1000);
            lt = new LatencyTimer(100, 1000);
        }
        }


        BAD_TOUCH_HACK = context.getResources().getBoolean(
        Resources r = context.getResources();
                com.android.internal.R.bool.config_filterTouchEvents);
        BAD_TOUCH_HACK = r.getBoolean(com.android.internal.R.bool.config_filterTouchEvents);
        
        JUMPY_TOUCH_HACK = r.getBoolean(com.android.internal.R.bool.config_filterJumpyTouchEvents);
        
        
        mHapticFeedbackCallback = hapticFeedbackCallback;
        mHapticFeedbackCallback = hapticFeedbackCallback;
        
        
@@ -758,6 +767,9 @@ public abstract class KeyInputQueue {
                                    if (BAD_TOUCH_HACK) {
                                    if (BAD_TOUCH_HACK) {
                                        ms.dropBadPoint(di);
                                        ms.dropBadPoint(di);
                                    }
                                    }
                                    if (JUMPY_TOUCH_HACK) {
                                        ms.dropJumpyPoint(di);
                                    }
                                    
                                    
                                    boolean doMotion = !monitorVirtualKey(di,
                                    boolean doMotion = !monitorVirtualKey(di,
                                            ev, curTime, curTimeNano);
                                            ev, curTime, curTimeNano);