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

This commit is contained in:
Treehugger Robot 2022-02-11 02:06:44 +00:00 committed by Gerrit Code Review
commit c4a8259f78

View File

@ -17,11 +17,13 @@ package com.android.server.policy;
import static android.view.KeyEvent.KEYCODE_POWER;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseLongArray;
import android.view.KeyEvent;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ToBooleanFunction;
import java.io.PrintWriter;
@ -35,13 +37,18 @@ public class KeyCombinationManager {
private static final String TAG = "KeyCombinationManager";
// Store the received down time of keycode.
@GuardedBy("mLock")
private final SparseLongArray mDownTimes = new SparseLongArray(2);
private final ArrayList<TwoKeysCombinationRule> mRules = new ArrayList();
// Selected rules according to current key down.
private final Object mLock = new Object();
@GuardedBy("mLock")
private final ArrayList<TwoKeysCombinationRule> mActiveRules = new ArrayList();
// The rule has been triggered by current keys.
@GuardedBy("mLock")
private TwoKeysCombinationRule mTriggeredRule;
private final Handler mHandler = new Handler();
// Keys in a key combination must be pressed within this interval of each other.
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.
*/
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 int keyCode = event.getKeyCode();
final int count = mActiveRules.size();
@ -154,7 +167,7 @@ public class KeyCombinationManager {
return false;
}
Log.v(TAG, "Performing combination rule : " + rule);
rule.execute();
mHandler.post(rule::execute);
mTriggeredRule = rule;
return true;
});
@ -169,7 +182,7 @@ public class KeyCombinationManager {
for (int index = count - 1; index >= 0; index--) {
final TwoKeysCombinationRule rule = mActiveRules.get(index);
if (rule.shouldInterceptKey(keyCode)) {
rule.cancel();
mHandler.post(rule::cancel);
mActiveRules.remove(index);
}
}
@ -181,31 +194,37 @@ public class KeyCombinationManager {
* Return the interceptTimeout to tell InputDispatcher when is ready to deliver to window.
*/
long getKeyInterceptTimeout(int keyCode) {
if (forAllActiveRules((rule) -> rule.shouldInterceptKey(keyCode))) {
return mDownTimes.get(keyCode) + COMBINE_KEY_DELAY_MILLIS;
synchronized (mLock) {
if (forAllActiveRules((rule) -> rule.shouldInterceptKey(keyCode))) {
return mDownTimes.get(keyCode) + COMBINE_KEY_DELAY_MILLIS;
}
return 0;
}
return 0;
}
/**
* True if the key event had been handled.
*/
boolean isKeyConsumed(KeyEvent event) {
if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) {
return false;
synchronized (mLock) {
if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) {
return false;
}
return mTriggeredRule != null && mTriggeredRule.shouldInterceptKey(event.getKeyCode());
}
return mTriggeredRule != null && mTriggeredRule.shouldInterceptKey(event.getKeyCode());
}
/**
* True if power key is the candidate.
*/
boolean isPowerKeyIntercepted() {
if (forAllActiveRules((rule) -> rule.shouldInterceptKey(KEYCODE_POWER))) {
// return false if only if power key pressed.
return mDownTimes.size() > 1 || mDownTimes.get(KEYCODE_POWER) == 0;
synchronized (mLock) {
if (forAllActiveRules((rule) -> rule.shouldInterceptKey(KEYCODE_POWER))) {
// return false if only if power key pressed.
return mDownTimes.size() > 1 || mDownTimes.get(KEYCODE_POWER) == 0;
}
return false;
}
return false;
}
/**