Merge "[Media ML] Support customization for single/double/triple clicks" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
142eceea7a
@@ -33,29 +33,28 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* Provides a way to customize behavior for media key events.
|
* Provides a way to customize behavior for media key events.
|
||||||
* <p>
|
* <p>
|
||||||
* In order to override the implementation of the single/double/triple click or long press,
|
* In order to override the implementation of the single/double/triple tap or long press,
|
||||||
* {@link #setOverriddenKeyEvents(int, int)} should be called for each key code with the
|
* {@link #setOverriddenKeyEvents(int, int)} should be called for each key code with the
|
||||||
* overridden {@link KeyEventType} bit value set, and the corresponding method,
|
* overridden {@link KeyEventType} bit value set, and the corresponding method,
|
||||||
* {@link #onSingleClick(KeyEvent)}, {@link #onDoubleClick(KeyEvent)},
|
* {@link #onSingleTap(KeyEvent)}, {@link #onDoubleTap(KeyEvent)},
|
||||||
* {@link #onTripleClick(KeyEvent)}, {@link #onLongPress(KeyEvent)} should be implemented.
|
* {@link #onTripleTap(KeyEvent)}, {@link #onLongPress(KeyEvent)} should be implemented.
|
||||||
* <p>
|
* <p>
|
||||||
* Note: When instantiating this class, {@link MediaSessionService} will only use the constructor
|
* Note: When instantiating this class, {@link MediaSessionService} will only use the constructor
|
||||||
* without any parameters.
|
* without any parameters.
|
||||||
*/
|
*/
|
||||||
// TODO: Change API names from using "click" to "tap"
|
|
||||||
// TODO: Move this class to apex/media/
|
// TODO: Move this class to apex/media/
|
||||||
public abstract class MediaKeyDispatcher {
|
public abstract class MediaKeyDispatcher {
|
||||||
@IntDef(flag = true, value = {
|
@IntDef(flag = true, value = {
|
||||||
KEY_EVENT_SINGLE_CLICK,
|
KEY_EVENT_SINGLE_TAP,
|
||||||
KEY_EVENT_DOUBLE_CLICK,
|
KEY_EVENT_DOUBLE_TAP,
|
||||||
KEY_EVENT_TRIPLE_CLICK,
|
KEY_EVENT_TRIPLE_TAP,
|
||||||
KEY_EVENT_LONG_PRESS
|
KEY_EVENT_LONG_PRESS
|
||||||
})
|
})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@interface KeyEventType {}
|
@interface KeyEventType {}
|
||||||
static final int KEY_EVENT_SINGLE_CLICK = 1 << 0;
|
static final int KEY_EVENT_SINGLE_TAP = 1 << 0;
|
||||||
static final int KEY_EVENT_DOUBLE_CLICK = 1 << 1;
|
static final int KEY_EVENT_DOUBLE_TAP = 1 << 1;
|
||||||
static final int KEY_EVENT_TRIPLE_CLICK = 1 << 2;
|
static final int KEY_EVENT_TRIPLE_TAP = 1 << 2;
|
||||||
static final int KEY_EVENT_LONG_PRESS = 1 << 3;
|
static final int KEY_EVENT_LONG_PRESS = 1 << 3;
|
||||||
|
|
||||||
private Map<Integer, Integer> mOverriddenKeyEvents;
|
private Map<Integer, Integer> mOverriddenKeyEvents;
|
||||||
@@ -110,16 +109,16 @@ public abstract class MediaKeyDispatcher {
|
|||||||
return mOverriddenKeyEvents;
|
return mOverriddenKeyEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isSingleClickOverridden(@KeyEventType int overriddenKeyEvents) {
|
static boolean isSingleTapOverridden(@KeyEventType int overriddenKeyEvents) {
|
||||||
return (overriddenKeyEvents & MediaKeyDispatcher.KEY_EVENT_SINGLE_CLICK) != 0;
|
return (overriddenKeyEvents & MediaKeyDispatcher.KEY_EVENT_SINGLE_TAP) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isDoubleClickOverridden(@KeyEventType int overriddenKeyEvents) {
|
static boolean isDoubleTapOverridden(@KeyEventType int overriddenKeyEvents) {
|
||||||
return (overriddenKeyEvents & MediaKeyDispatcher.KEY_EVENT_DOUBLE_CLICK) != 0;
|
return (overriddenKeyEvents & MediaKeyDispatcher.KEY_EVENT_DOUBLE_TAP) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isTripleClickOverridden(@KeyEventType int overriddenKeyEvents) {
|
static boolean isTripleTapOverridden(@KeyEventType int overriddenKeyEvents) {
|
||||||
return (overriddenKeyEvents & MediaKeyDispatcher.KEY_EVENT_TRIPLE_CLICK) != 0;
|
return (overriddenKeyEvents & MediaKeyDispatcher.KEY_EVENT_TRIPLE_TAP) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isLongPressOverridden(@KeyEventType int overriddenKeyEvents) {
|
static boolean isLongPressOverridden(@KeyEventType int overriddenKeyEvents) {
|
||||||
@@ -150,11 +149,11 @@ public abstract class MediaKeyDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customized implementation for single click event. Will be run if
|
* Customized implementation for single tap event. Will be run if
|
||||||
* {@link #KEY_EVENT_SINGLE_CLICK} flag is on for the corresponding key code from
|
* {@link #KEY_EVENT_SINGLE_TAP} flag is on for the corresponding key code from
|
||||||
* {@link #getOverriddenKeyEvents()}.
|
* {@link #getOverriddenKeyEvents()}.
|
||||||
*
|
*
|
||||||
* It is considered a single click if only one {@link KeyEvent} with the same
|
* It is considered a single tap if only one {@link KeyEvent} with the same
|
||||||
* {@link KeyEvent#getKeyCode()} is dispatched within
|
* {@link KeyEvent#getKeyCode()} is dispatched within
|
||||||
* {@link ViewConfiguration#getMultiPressTimeout()} milliseconds. Change the
|
* {@link ViewConfiguration#getMultiPressTimeout()} milliseconds. Change the
|
||||||
* {@link android.provider.Settings.Secure#MULTI_PRESS_TIMEOUT} value to adjust the interval.
|
* {@link android.provider.Settings.Secure#MULTI_PRESS_TIMEOUT} value to adjust the interval.
|
||||||
@@ -163,15 +162,15 @@ public abstract class MediaKeyDispatcher {
|
|||||||
*
|
*
|
||||||
* @param keyEvent
|
* @param keyEvent
|
||||||
*/
|
*/
|
||||||
void onSingleClick(KeyEvent keyEvent) {
|
void onSingleTap(KeyEvent keyEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customized implementation for double click event. Will be run if
|
* Customized implementation for double tap event. Will be run if
|
||||||
* {@link #KEY_EVENT_DOUBLE_CLICK} flag is on for the corresponding key code from
|
* {@link #KEY_EVENT_DOUBLE_TAP} flag is on for the corresponding key code from
|
||||||
* {@link #getOverriddenKeyEvents()}.
|
* {@link #getOverriddenKeyEvents()}.
|
||||||
*
|
*
|
||||||
* It is considered a double click if two {@link KeyEvent}s with the same
|
* It is considered a double tap if two {@link KeyEvent}s with the same
|
||||||
* {@link KeyEvent#getKeyCode()} are dispatched within
|
* {@link KeyEvent#getKeyCode()} are dispatched within
|
||||||
* {@link ViewConfiguration#getMultiPressTimeout()} milliseconds of each other. Change the
|
* {@link ViewConfiguration#getMultiPressTimeout()} milliseconds of each other. Change the
|
||||||
* {@link android.provider.Settings.Secure#MULTI_PRESS_TIMEOUT} value to adjust the interval.
|
* {@link android.provider.Settings.Secure#MULTI_PRESS_TIMEOUT} value to adjust the interval.
|
||||||
@@ -180,15 +179,15 @@ public abstract class MediaKeyDispatcher {
|
|||||||
*
|
*
|
||||||
* @param keyEvent
|
* @param keyEvent
|
||||||
*/
|
*/
|
||||||
void onDoubleClick(KeyEvent keyEvent) {
|
void onDoubleTap(KeyEvent keyEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customized implementation for triple click event. Will be run if
|
* Customized implementation for triple tap event. Will be run if
|
||||||
* {@link #KEY_EVENT_TRIPLE_CLICK} flag is on for the corresponding key code from
|
* {@link #KEY_EVENT_TRIPLE_TAP} flag is on for the corresponding key code from
|
||||||
* {@link #getOverriddenKeyEvents()}.
|
* {@link #getOverriddenKeyEvents()}.
|
||||||
*
|
*
|
||||||
* It is considered a triple click if three {@link KeyEvent}s with the same
|
* It is considered a triple tap if three {@link KeyEvent}s with the same
|
||||||
* {@link KeyEvent#getKeyCode()} are dispatched within
|
* {@link KeyEvent#getKeyCode()} are dispatched within
|
||||||
* {@link ViewConfiguration#getMultiPressTimeout()} milliseconds of each other. Change the
|
* {@link ViewConfiguration#getMultiPressTimeout()} milliseconds of each other. Change the
|
||||||
* {@link android.provider.Settings.Secure#MULTI_PRESS_TIMEOUT} value to adjust the interval.
|
* {@link android.provider.Settings.Secure#MULTI_PRESS_TIMEOUT} value to adjust the interval.
|
||||||
@@ -197,7 +196,7 @@ public abstract class MediaKeyDispatcher {
|
|||||||
*
|
*
|
||||||
* @param keyEvent
|
* @param keyEvent
|
||||||
*/
|
*/
|
||||||
void onTripleClick(KeyEvent keyEvent) {
|
void onTripleTap(KeyEvent keyEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ package com.android.server.media;
|
|||||||
|
|
||||||
import static android.os.UserHandle.USER_ALL;
|
import static android.os.UserHandle.USER_ALL;
|
||||||
|
|
||||||
|
import static com.android.server.media.MediaKeyDispatcher.KEY_EVENT_LONG_PRESS;
|
||||||
|
import static com.android.server.media.MediaKeyDispatcher.isDoubleTapOverridden;
|
||||||
|
import static com.android.server.media.MediaKeyDispatcher.isLongPressOverridden;
|
||||||
|
import static com.android.server.media.MediaKeyDispatcher.isSingleTapOverridden;
|
||||||
|
import static com.android.server.media.MediaKeyDispatcher.isTripleTapOverridden;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.INotificationManager;
|
import android.app.INotificationManager;
|
||||||
import android.app.KeyguardManager;
|
import android.app.KeyguardManager;
|
||||||
@@ -105,7 +111,7 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
private static final int SESSION_CREATION_LIMIT_PER_UID = 100;
|
private static final int SESSION_CREATION_LIMIT_PER_UID = 100;
|
||||||
private static final int LONG_PRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout()
|
private static final int LONG_PRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout()
|
||||||
+ /* Buffer for delayed delivery of key event */ 50;
|
+ /* Buffer for delayed delivery of key event */ 50;
|
||||||
private static final int MULTI_PRESS_TIMEOUT = ViewConfiguration.getMultiPressTimeout();
|
private static final int MULTI_TAP_TIMEOUT = ViewConfiguration.getMultiPressTimeout();
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final SessionManagerImpl mSessionManagerImpl;
|
private final SessionManagerImpl mSessionManagerImpl;
|
||||||
@@ -1101,9 +1107,12 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
"android.media.AudioService.WAKELOCK_ACQUIRED";
|
"android.media.AudioService.WAKELOCK_ACQUIRED";
|
||||||
private static final int WAKELOCK_RELEASE_ON_FINISHED = 1980; // magic number
|
private static final int WAKELOCK_RELEASE_ON_FINISHED = 1980; // magic number
|
||||||
|
|
||||||
private KeyEvent mPendingFirstDownKeyEvent = null;
|
private KeyEvent mTrackingFirstDownKeyEvent = null;
|
||||||
private boolean mIsLongPressing = false;
|
private boolean mIsLongPressing = false;
|
||||||
private Runnable mLongPressTimeoutRunnable = null;
|
private Runnable mLongPressTimeoutRunnable = null;
|
||||||
|
private int mMultiTapCount = 0;
|
||||||
|
private int mMultiTapKeyCode = 0;
|
||||||
|
private Runnable mMultiTapTimeoutRunnable = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
|
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
|
||||||
@@ -2117,10 +2126,12 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A long press is determined by:
|
// A long press is determined by:
|
||||||
// 1) A KeyEvent with KeyEvent.ACTION_DOWN and repeat count of 0, followed by
|
// 1) A KeyEvent.ACTION_DOWN KeyEvent and repeat count of 0, followed by
|
||||||
// 2) A KeyEvent with KeyEvent.ACTION_DOWN and repeat count of 1 and FLAG_LONG_PRESS within
|
// 2) A KeyEvent.ACTION_DOWN KeyEvent with the same key code, a repeat count of 1, and
|
||||||
// ViewConfiguration.getLongPressTimeout().
|
// FLAG_LONG_PRESS received within ViewConfiguration.getLongPressTimeout().
|
||||||
// TODO: Add description about what a click is determined by.
|
// A tap is determined by:
|
||||||
|
// 1) A KeyEvent.ACTION_DOWN KeyEvent followed by
|
||||||
|
// 2) A KeyEvent.ACTION_UP KeyEvent with the same key code.
|
||||||
private void handleKeyEventLocked(String packageName, int pid, int uid,
|
private void handleKeyEventLocked(String packageName, int pid, int uid,
|
||||||
boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
|
boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
|
||||||
if (keyEvent.isCanceled()) {
|
if (keyEvent.isCanceled()) {
|
||||||
@@ -2129,61 +2140,121 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
|
|
||||||
int overriddenKeyEvents = (mCustomMediaKeyDispatcher == null) ? 0
|
int overriddenKeyEvents = (mCustomMediaKeyDispatcher == null) ? 0
|
||||||
: mCustomMediaKeyDispatcher.getOverriddenKeyEvents().get(keyEvent.getKeyCode());
|
: mCustomMediaKeyDispatcher.getOverriddenKeyEvents().get(keyEvent.getKeyCode());
|
||||||
cancelPendingIfNeeded(keyEvent);
|
cancelTrackingIfNeeded(packageName, pid, uid, asSystemService, keyEvent, needWakeLock,
|
||||||
if (!needPending(keyEvent, overriddenKeyEvents)) {
|
overriddenKeyEvents);
|
||||||
|
if (!needTracking(keyEvent, overriddenKeyEvents)) {
|
||||||
dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService, keyEvent,
|
dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService, keyEvent,
|
||||||
needWakeLock);
|
needWakeLock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFirstDownKeyEvent(keyEvent)) {
|
if (isFirstDownKeyEvent(keyEvent)) {
|
||||||
mPendingFirstDownKeyEvent = keyEvent;
|
mTrackingFirstDownKeyEvent = keyEvent;
|
||||||
mIsLongPressing = false;
|
mIsLongPressing = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Long press is always overridden here, otherwise the key event would have been already
|
||||||
|
// handled
|
||||||
if (isFirstLongPressKeyEvent(keyEvent)) {
|
if (isFirstLongPressKeyEvent(keyEvent)) {
|
||||||
mIsLongPressing = true;
|
mIsLongPressing = true;
|
||||||
}
|
}
|
||||||
if (mIsLongPressing) {
|
if (mIsLongPressing) {
|
||||||
handleLongPressLocked(keyEvent, needWakeLock, overriddenKeyEvents);
|
handleLongPressLocked(keyEvent, needWakeLock, overriddenKeyEvents);
|
||||||
} else if (keyEvent.getAction() == KeyEvent.ACTION_UP) {
|
return;
|
||||||
mPendingFirstDownKeyEvent = null;
|
}
|
||||||
// TODO: Replace this with code to determine whether
|
|
||||||
// single/double/triple click and run custom implementations,
|
if (keyEvent.getAction() == KeyEvent.ACTION_UP) {
|
||||||
// if they exist.
|
mTrackingFirstDownKeyEvent = null;
|
||||||
|
if (shouldTrackForMultipleTapsLocked(overriddenKeyEvents)) {
|
||||||
|
if (mMultiTapCount == 0) {
|
||||||
|
mMultiTapTimeoutRunnable = createSingleTapRunnable(packageName, pid, uid,
|
||||||
|
asSystemService, keyEvent, needWakeLock,
|
||||||
|
isSingleTapOverridden(overriddenKeyEvents));
|
||||||
|
if (isSingleTapOverridden(overriddenKeyEvents)
|
||||||
|
&& !isDoubleTapOverridden(overriddenKeyEvents)
|
||||||
|
&& !isTripleTapOverridden(overriddenKeyEvents)) {
|
||||||
|
mMultiTapTimeoutRunnable.run();
|
||||||
|
} else {
|
||||||
|
mHandler.postDelayed(mMultiTapTimeoutRunnable,
|
||||||
|
MULTI_TAP_TIMEOUT);
|
||||||
|
mMultiTapCount = 1;
|
||||||
|
mMultiTapKeyCode = keyEvent.getKeyCode();
|
||||||
|
}
|
||||||
|
} else if (mMultiTapCount == 1) {
|
||||||
|
mHandler.removeCallbacks(mMultiTapTimeoutRunnable);
|
||||||
|
mMultiTapTimeoutRunnable = createDoubleTapRunnable(packageName, pid, uid,
|
||||||
|
asSystemService, keyEvent, needWakeLock,
|
||||||
|
isSingleTapOverridden(overriddenKeyEvents),
|
||||||
|
isDoubleTapOverridden(overriddenKeyEvents));
|
||||||
|
if (isTripleTapOverridden(overriddenKeyEvents)) {
|
||||||
|
mHandler.postDelayed(mMultiTapTimeoutRunnable, MULTI_TAP_TIMEOUT);
|
||||||
|
mMultiTapCount = 2;
|
||||||
|
} else {
|
||||||
|
mMultiTapTimeoutRunnable.run();
|
||||||
|
}
|
||||||
|
} else if (mMultiTapCount == 2) {
|
||||||
|
mHandler.removeCallbacks(mMultiTapTimeoutRunnable);
|
||||||
|
onTripleTap(keyEvent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
dispatchDownAndUpKeyEventsLocked(packageName, pid, uid, asSystemService,
|
dispatchDownAndUpKeyEventsLocked(packageName, pid, uid, asSystemService,
|
||||||
keyEvent, needWakeLock);
|
keyEvent, needWakeLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void cancelPendingIfNeeded(KeyEvent keyEvent) {
|
private boolean shouldTrackForMultipleTapsLocked(int overriddenKeyEvents) {
|
||||||
if (mPendingFirstDownKeyEvent == null) {
|
return isSingleTapOverridden(overriddenKeyEvents)
|
||||||
|
|| isDoubleTapOverridden(overriddenKeyEvents)
|
||||||
|
|| isTripleTapOverridden(overriddenKeyEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelTrackingIfNeeded(String packageName, int pid, int uid,
|
||||||
|
boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock,
|
||||||
|
int overriddenKeyEvents) {
|
||||||
|
if (mTrackingFirstDownKeyEvent == null && mMultiTapTimeoutRunnable == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFirstDownKeyEvent(keyEvent)) {
|
if (isFirstDownKeyEvent(keyEvent)) {
|
||||||
if (mLongPressTimeoutRunnable != null) {
|
if (mLongPressTimeoutRunnable != null) {
|
||||||
mHandler.removeCallbacks(mLongPressTimeoutRunnable);
|
mHandler.removeCallbacks(mLongPressTimeoutRunnable);
|
||||||
mLongPressTimeoutRunnable.run();
|
mLongPressTimeoutRunnable.run();
|
||||||
} else {
|
|
||||||
resetLongPressTracking();
|
|
||||||
}
|
}
|
||||||
|
if (mMultiTapTimeoutRunnable != null && keyEvent.getKeyCode() != mMultiTapKeyCode) {
|
||||||
|
runExistingMultiTapRunnableLocked();
|
||||||
|
}
|
||||||
|
resetLongPressTracking();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mPendingFirstDownKeyEvent.getDownTime() == keyEvent.getDownTime()
|
|
||||||
&& mPendingFirstDownKeyEvent.getKeyCode() == keyEvent.getKeyCode()
|
if (mTrackingFirstDownKeyEvent != null
|
||||||
&& keyEvent.getAction() == KeyEvent.ACTION_DOWN
|
&& mTrackingFirstDownKeyEvent.getDownTime() == keyEvent.getDownTime()
|
||||||
&& keyEvent.getRepeatCount() > 1 && !mIsLongPressing) {
|
&& mTrackingFirstDownKeyEvent.getKeyCode() == keyEvent.getKeyCode()
|
||||||
|
&& keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
|
||||||
|
if (isFirstLongPressKeyEvent(keyEvent)) {
|
||||||
|
if (mMultiTapTimeoutRunnable != null) {
|
||||||
|
runExistingMultiTapRunnableLocked();
|
||||||
|
}
|
||||||
|
if ((overriddenKeyEvents & KEY_EVENT_LONG_PRESS) == 0
|
||||||
|
&& !isVoiceKey(keyEvent.getKeyCode())) {
|
||||||
|
dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
|
||||||
|
mTrackingFirstDownKeyEvent, needWakeLock);
|
||||||
|
mTrackingFirstDownKeyEvent = null;
|
||||||
|
}
|
||||||
|
} else if (keyEvent.getRepeatCount() > 1 && !mIsLongPressing) {
|
||||||
resetLongPressTracking();
|
resetLongPressTracking();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean needPending(KeyEvent keyEvent, int overriddenKeyEvents) {
|
private boolean needTracking(KeyEvent keyEvent, int overriddenKeyEvents) {
|
||||||
if (!isFirstDownKeyEvent(keyEvent)) {
|
if (!isFirstDownKeyEvent(keyEvent)) {
|
||||||
if (mPendingFirstDownKeyEvent == null) {
|
if (mTrackingFirstDownKeyEvent == null) {
|
||||||
return false;
|
return false;
|
||||||
} else if (mPendingFirstDownKeyEvent.getDownTime() != keyEvent.getDownTime()
|
} else if (mTrackingFirstDownKeyEvent.getDownTime() != keyEvent.getDownTime()
|
||||||
|| mPendingFirstDownKeyEvent.getKeyCode() != keyEvent.getKeyCode()) {
|
|| mTrackingFirstDownKeyEvent.getKeyCode() != keyEvent.getKeyCode()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2193,10 +2264,21 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void runExistingMultiTapRunnableLocked() {
|
||||||
|
mHandler.removeCallbacks(mMultiTapTimeoutRunnable);
|
||||||
|
mMultiTapTimeoutRunnable.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetMultiTapTrackingLocked() {
|
||||||
|
mMultiTapCount = 0;
|
||||||
|
mMultiTapTimeoutRunnable = null;
|
||||||
|
mMultiTapKeyCode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
private void handleLongPressLocked(KeyEvent keyEvent, boolean needWakeLock,
|
private void handleLongPressLocked(KeyEvent keyEvent, boolean needWakeLock,
|
||||||
int overriddenKeyEvents) {
|
int overriddenKeyEvents) {
|
||||||
if (mCustomMediaKeyDispatcher != null
|
if (mCustomMediaKeyDispatcher != null
|
||||||
&& mCustomMediaKeyDispatcher.isLongPressOverridden(overriddenKeyEvents)) {
|
&& isLongPressOverridden(overriddenKeyEvents)) {
|
||||||
mCustomMediaKeyDispatcher.onLongPress(keyEvent);
|
mCustomMediaKeyDispatcher.onLongPress(keyEvent);
|
||||||
|
|
||||||
if (mLongPressTimeoutRunnable != null) {
|
if (mLongPressTimeoutRunnable != null) {
|
||||||
@@ -2230,7 +2312,7 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void resetLongPressTracking() {
|
private void resetLongPressTracking() {
|
||||||
mPendingFirstDownKeyEvent = null;
|
mTrackingFirstDownKeyEvent = null;
|
||||||
mIsLongPressing = false;
|
mIsLongPressing = false;
|
||||||
mLongPressTimeoutRunnable = null;
|
mLongPressTimeoutRunnable = null;
|
||||||
}
|
}
|
||||||
@@ -2259,6 +2341,50 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
keyEvent, needWakeLock);
|
keyEvent, needWakeLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Runnable createSingleTapRunnable(String packageName, int pid, int uid,
|
||||||
|
boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock,
|
||||||
|
boolean overridden) {
|
||||||
|
return new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
resetMultiTapTrackingLocked();
|
||||||
|
if (overridden) {
|
||||||
|
mCustomMediaKeyDispatcher.onSingleTap(keyEvent);
|
||||||
|
} else {
|
||||||
|
dispatchDownAndUpKeyEventsLocked(packageName, pid, uid, asSystemService,
|
||||||
|
keyEvent, needWakeLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Runnable createDoubleTapRunnable(String packageName, int pid, int uid,
|
||||||
|
boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock,
|
||||||
|
boolean singleTapOverridden, boolean doubleTapOverridden) {
|
||||||
|
return new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
resetMultiTapTrackingLocked();
|
||||||
|
if (doubleTapOverridden) {
|
||||||
|
mCustomMediaKeyDispatcher.onDoubleTap(keyEvent);
|
||||||
|
} else if (singleTapOverridden) {
|
||||||
|
mCustomMediaKeyDispatcher.onSingleTap(keyEvent);
|
||||||
|
mCustomMediaKeyDispatcher.onSingleTap(keyEvent);
|
||||||
|
} else {
|
||||||
|
dispatchDownAndUpKeyEventsLocked(packageName, pid, uid, asSystemService,
|
||||||
|
keyEvent, needWakeLock);
|
||||||
|
dispatchDownAndUpKeyEventsLocked(packageName, pid, uid, asSystemService,
|
||||||
|
keyEvent, needWakeLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
private void onTripleTap(KeyEvent keyEvent) {
|
||||||
|
resetMultiTapTrackingLocked();
|
||||||
|
mCustomMediaKeyDispatcher.onTripleTap(keyEvent);
|
||||||
|
}
|
||||||
|
|
||||||
private void dispatchMediaKeyEventLocked(String packageName, int pid, int uid,
|
private void dispatchMediaKeyEventLocked(String packageName, int pid, int uid,
|
||||||
boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
|
boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
|
||||||
if (mCurrentFullUserRecord.getMediaButtonSessionLocked()
|
if (mCurrentFullUserRecord.getMediaButtonSessionLocked()
|
||||||
|
|||||||
Reference in New Issue
Block a user