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

Commit d88b35d6 authored by Arthur Hung's avatar Arthur Hung Committed by Automerger Merge Worker
Browse files

Merge "Fix potential exception while pressing volume up and volume down" into...

Merge "Fix potential exception while pressing volume up and volume down" into sc-v2-dev am: b09275f1 am: 8605801a

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16439834

Change-Id: Ic5c46a86d1107b9219399161a2fc177508eee80b
parents 9191d837 8605801a
Loading
Loading
Loading
Loading
+31 −12
Original line number Original line Diff line number Diff line
@@ -17,11 +17,13 @@ package com.android.server.policy;


import static android.view.KeyEvent.KEYCODE_POWER;
import static android.view.KeyEvent.KEYCODE_POWER;


import android.os.Handler;
import android.os.SystemClock;
import android.os.SystemClock;
import android.util.Log;
import android.util.Log;
import android.util.SparseLongArray;
import android.util.SparseLongArray;
import android.view.KeyEvent;
import android.view.KeyEvent;


import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.util.ToBooleanFunction;


import java.io.PrintWriter;
import java.io.PrintWriter;
@@ -35,13 +37,18 @@ public class KeyCombinationManager {
    private static final String TAG = "KeyCombinationManager";
    private static final String TAG = "KeyCombinationManager";


    // Store the received down time of keycode.
    // Store the received down time of keycode.
    @GuardedBy("mLock")
    private final SparseLongArray mDownTimes = new SparseLongArray(2);
    private final SparseLongArray mDownTimes = new SparseLongArray(2);
    private final ArrayList<TwoKeysCombinationRule> mRules = new ArrayList();
    private final ArrayList<TwoKeysCombinationRule> mRules = new ArrayList();


    // Selected rules according to current key down.
    // Selected rules according to current key down.
    private final Object mLock = new Object();
    @GuardedBy("mLock")
    private final ArrayList<TwoKeysCombinationRule> mActiveRules = new ArrayList();
    private final ArrayList<TwoKeysCombinationRule> mActiveRules = new ArrayList();
    // The rule has been triggered by current keys.
    // The rule has been triggered by current keys.
    @GuardedBy("mLock")
    private TwoKeysCombinationRule mTriggeredRule;
    private TwoKeysCombinationRule mTriggeredRule;
    private final Handler mHandler = new Handler();


    // Keys in a key combination must be pressed within this interval of each other.
    // Keys in a key combination must be pressed within this interval of each other.
    private static final long COMBINE_KEY_DELAY_MILLIS = 150;
    private static final long COMBINE_KEY_DELAY_MILLIS = 150;
@@ -109,6 +116,12 @@ public class KeyCombinationManager {
     * Return true if any active rule could be triggered by the key event, otherwise false.
     * Return true if any active rule could be triggered by the key event, otherwise false.
     */
     */
    boolean interceptKey(KeyEvent event, boolean interactive) {
    boolean interceptKey(KeyEvent event, boolean interactive) {
        synchronized (mLock) {
            return interceptKeyLocked(event, interactive);
        }
    }

    private boolean interceptKeyLocked(KeyEvent event, boolean interactive) {
        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
        final int keyCode = event.getKeyCode();
        final int keyCode = event.getKeyCode();
        final int count = mActiveRules.size();
        final int count = mActiveRules.size();
@@ -154,7 +167,7 @@ public class KeyCombinationManager {
                        return false;
                        return false;
                    }
                    }
                    Log.v(TAG, "Performing combination rule : " + rule);
                    Log.v(TAG, "Performing combination rule : " + rule);
                    rule.execute();
                    mHandler.post(rule::execute);
                    mTriggeredRule = rule;
                    mTriggeredRule = rule;
                    return true;
                    return true;
                });
                });
@@ -169,7 +182,7 @@ public class KeyCombinationManager {
            for (int index = count - 1; index >= 0; index--) {
            for (int index = count - 1; index >= 0; index--) {
                final TwoKeysCombinationRule rule = mActiveRules.get(index);
                final TwoKeysCombinationRule rule = mActiveRules.get(index);
                if (rule.shouldInterceptKey(keyCode)) {
                if (rule.shouldInterceptKey(keyCode)) {
                    rule.cancel();
                    mHandler.post(rule::cancel);
                    mActiveRules.remove(index);
                    mActiveRules.remove(index);
                }
                }
            }
            }
@@ -181,32 +194,38 @@ public class KeyCombinationManager {
     * Return the interceptTimeout to tell InputDispatcher when is ready to deliver to window.
     * Return the interceptTimeout to tell InputDispatcher when is ready to deliver to window.
     */
     */
    long getKeyInterceptTimeout(int keyCode) {
    long getKeyInterceptTimeout(int keyCode) {
        synchronized (mLock) {
            if (forAllActiveRules((rule) -> rule.shouldInterceptKey(keyCode))) {
            if (forAllActiveRules((rule) -> rule.shouldInterceptKey(keyCode))) {
                return mDownTimes.get(keyCode) + COMBINE_KEY_DELAY_MILLIS;
                return mDownTimes.get(keyCode) + COMBINE_KEY_DELAY_MILLIS;
            }
            }
            return 0;
            return 0;
        }
        }
    }


    /**
    /**
     * True if the key event had been handled.
     * True if the key event had been handled.
     */
     */
    boolean isKeyConsumed(KeyEvent event) {
    boolean isKeyConsumed(KeyEvent event) {
        synchronized (mLock) {
            if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) {
            if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) {
                return false;
                return false;
            }
            }
            return mTriggeredRule != null && mTriggeredRule.shouldInterceptKey(event.getKeyCode());
            return mTriggeredRule != null && mTriggeredRule.shouldInterceptKey(event.getKeyCode());
        }
        }
    }


    /**
    /**
     * True if power key is the candidate.
     * True if power key is the candidate.
     */
     */
    boolean isPowerKeyIntercepted() {
    boolean isPowerKeyIntercepted() {
        synchronized (mLock) {
            if (forAllActiveRules((rule) -> rule.shouldInterceptKey(KEYCODE_POWER))) {
            if (forAllActiveRules((rule) -> rule.shouldInterceptKey(KEYCODE_POWER))) {
                // return false if only if power key pressed.
                // return false if only if power key pressed.
                return mDownTimes.size() > 1 || mDownTimes.get(KEYCODE_POWER) == 0;
                return mDownTimes.size() > 1 || mDownTimes.get(KEYCODE_POWER) == 0;
            }
            }
            return false;
            return false;
        }
        }
    }


    /**
    /**
     * Traverse each item of rules.
     * Traverse each item of rules.