Merge "DO NOT MERGE. Improve screenshot chord debouncing. Bug: 5011907" into ics-mr0

This commit is contained in:
Winson Chung
2011-10-12 17:00:11 -07:00
committed by Android (Google) Code Review
8 changed files with 253 additions and 173 deletions

View File

@ -104,23 +104,23 @@ public interface WindowManagerPolicy {
*/
public final static String EXTRA_HDMI_PLUGGED_STATE = "state";
// flags for interceptKeyTq
/**
* Pass this event to the user / app. To be returned from {@link #interceptKeyTq}.
* Pass this event to the user / app. To be returned from
* {@link #interceptKeyBeforeQueueing}.
*/
public final static int ACTION_PASS_TO_USER = 0x00000001;
/**
* This key event should extend the user activity timeout and turn the lights on.
* To be returned from {@link #interceptKeyTq}. Do not return this and
* {@link #ACTION_GO_TO_SLEEP} or {@link #ACTION_PASS_TO_USER}.
* To be returned from {@link #interceptKeyBeforeQueueing}.
* Do not return this and {@link #ACTION_GO_TO_SLEEP} or {@link #ACTION_PASS_TO_USER}.
*/
public final static int ACTION_POKE_USER_ACTIVITY = 0x00000002;
/**
* This key event should put the device to sleep (and engage keyguard if necessary)
* To be returned from {@link #interceptKeyTq}. Do not return this and
* {@link #ACTION_POKE_USER_ACTIVITY} or {@link #ACTION_PASS_TO_USER}.
* To be returned from {@link #interceptKeyBeforeQueueing}.
* Do not return this and {@link #ACTION_POKE_USER_ACTIVITY} or {@link #ACTION_PASS_TO_USER}.
*/
public final static int ACTION_GO_TO_SLEEP = 0x00000004;
@ -677,10 +677,12 @@ public interface WindowManagerPolicy {
* event will normally go.
* @param event The key event.
* @param policyFlags The policy flags associated with the key.
* @return Returns true if the policy consumed the event and it should
* not be further dispatched.
* @return 0 if the key should be dispatched immediately, -1 if the key should
* not be dispatched ever, or a positive value indicating the number of
* milliseconds by which the key dispatch should be delayed before trying
* again.
*/
public boolean interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags);
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags);
/**
* Called from the input dispatcher thread when an application did not handle

View File

@ -267,7 +267,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
WindowState mKeyguard = null;
KeyguardViewMediator mKeyguardMediator;
GlobalActions mGlobalActions;
volatile boolean mPowerKeyHandled;
volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
boolean mPendingPowerKeyUpCanceled;
RecentApplicationsDialog mRecentAppsDialog;
Handler mHandler;
@ -403,8 +404,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private int mLongPressOnHomeBehavior = -1;
// Screenshot trigger states
private boolean mVolumeDownTriggered;
private boolean mPowerDownTriggered;
// Time to volume and power must be pressed within this interval of each other.
private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
private boolean mVolumeDownKeyTriggered;
private long mVolumeDownKeyTime;
private boolean mVolumeDownKeyConsumedByScreenshotChord;
private boolean mVolumeUpKeyTriggered;
private boolean mPowerKeyTriggered;
private long mPowerKeyTime;
ShortcutManager mShortcutManager;
PowerManager.WakeLock mBroadcastWakeLock;
@ -552,37 +559,64 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (!mPowerKeyHandled) {
mHandler.removeCallbacks(mPowerLongPress);
return !canceled;
} else {
mPowerKeyHandled = true;
return false;
}
return false;
}
private void cancelPendingPowerKeyAction() {
if (!mPowerKeyHandled) {
mHandler.removeCallbacks(mPowerLongPress);
}
mPendingPowerKeyUpCanceled = true;
}
private void interceptScreenshotChord() {
if (mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
final long now = SystemClock.uptimeMillis();
if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
&& now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
mVolumeDownKeyConsumedByScreenshotChord = true;
cancelPendingPowerKeyAction();
mHandler.postDelayed(mScreenshotChordLongPress,
ViewConfiguration.getGlobalActionKeyTimeout());
}
}
}
private void cancelPendingScreenshotChordAction() {
mHandler.removeCallbacks(mScreenshotChordLongPress);
}
private final Runnable mPowerLongPress = new Runnable() {
public void run() {
if (!mPowerKeyHandled) {
// The context isn't read
if (mLongPressOnPowerBehavior < 0) {
mLongPressOnPowerBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnPowerBehavior);
}
switch (mLongPressOnPowerBehavior) {
case LONG_PRESS_POWER_NOTHING:
break;
case LONG_PRESS_POWER_GLOBAL_ACTIONS:
mPowerKeyHandled = true;
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
showGlobalActionsDialog();
break;
case LONG_PRESS_POWER_SHUT_OFF:
mPowerKeyHandled = true;
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
ShutdownThread.shutdown(mContext, true);
break;
}
// The context isn't read
if (mLongPressOnPowerBehavior < 0) {
mLongPressOnPowerBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnPowerBehavior);
}
switch (mLongPressOnPowerBehavior) {
case LONG_PRESS_POWER_NOTHING:
break;
case LONG_PRESS_POWER_GLOBAL_ACTIONS:
mPowerKeyHandled = true;
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
showGlobalActionsDialog();
break;
case LONG_PRESS_POWER_SHUT_OFF:
mPowerKeyHandled = true;
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
ShutdownThread.shutdown(mContext, true);
break;
}
}
};
private final Runnable mScreenshotChordLongPress = new Runnable() {
public void run() {
takeScreenshot();
}
};
@ -1381,11 +1415,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
@Override
public boolean interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
final boolean keyguardOn = keyguardOn();
final int keyCode = event.getKeyCode();
final int repeatCount = event.getRepeatCount();
final int metaState = event.getMetaState();
final int flags = event.getFlags();
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
@ -1394,6 +1429,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
+ repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
}
// If we think we might have a volume down & power key chord on the way
// but we're not sure, then tell the dispatcher to wait a little while and
// try again later before dispatching.
if ((flags & KeyEvent.FLAG_FALLBACK) == 0) {
if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
final long now = SystemClock.uptimeMillis();
final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
if (now < timeoutTime) {
return timeoutTime - now;
}
}
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
&& mVolumeDownKeyConsumedByScreenshotChord) {
if (!down) {
mVolumeDownKeyConsumedByScreenshotChord = false;
}
return -1;
}
}
// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
// it handle it, because that gives us the correct 5 second
@ -1425,7 +1480,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
Log.i(TAG, "Ignoring HOME; event canceled.");
}
return true;
return -1;
}
// If a system window has focus, then it doesn't make sense
@ -1436,13 +1491,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
// the "app" is keyguard, so give it the key
return false;
return 0;
}
final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
for (int i=0; i<typeCount; i++) {
if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
// don't do anything, but also don't pass it to the app
return true;
return -1;
}
}
}
@ -1456,7 +1511,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
}
return true;
return -1;
} else if (keyCode == KeyEvent.KEYCODE_MENU) {
// Hijack modified menu keys for debugging features
final int chordBug = KeyEvent.META_SHIFT_ON;
@ -1465,7 +1520,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
mContext.sendOrderedBroadcast(intent, null);
return true;
return -1;
} else if (SHOW_PROCESSES_ON_ALT_MENU &&
(metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
Intent service = new Intent();
@ -1480,7 +1535,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
Settings.System.putInt(
res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
return true;
return -1;
}
}
} else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
@ -1493,15 +1548,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mShortcutKeyPressed = -1;
if (mConsumeShortcutKeyUp) {
mConsumeShortcutKeyUp = false;
return true;
return -1;
}
}
return false;
return 0;
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
if (down && repeatCount == 0) {
showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
}
return true;
return -1;
}
// Shortcuts are invoked through Search+key, so intercept those here
@ -1531,11 +1586,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
+ "+" + KeyEvent.keyCodeToString(keyCode));
}
}
return true;
return -1;
}
}
return false;
return 0;
}
/** {@inheritDoc} */
@ -1606,7 +1661,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
flags, event.getSource(), null);
int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
if ((actions & ACTION_PASS_TO_USER) != 0) {
if (!interceptKeyBeforeDispatching(win, fallbackEvent, policyFlags)) {
long delayMillis = interceptKeyBeforeDispatching(
win, fallbackEvent, policyFlags);
if (delayMillis == 0) {
if (DEBUG_FALLBACK) {
Slog.d(TAG, "Performing fallback.");
}
@ -2472,76 +2529,65 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final Object mScreenshotLock = new Object();
ServiceConnection mScreenshotConnection = null;
Runnable mScreenshotTimeout = null;
void finishScreenshotLSS(ServiceConnection conn) {
if (mScreenshotConnection == conn) {
mContext.unbindService(conn);
mScreenshotConnection = null;
if (mScreenshotTimeout != null) {
mHandler.removeCallbacks(mScreenshotTimeout);
mScreenshotTimeout = null;
}
}
}
private void takeScreenshot() {
mHandler.post(new Runnable() {
@Override
public void run() {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) {
return;
}
ComponentName cn = new ComponentName("com.android.systemui",
"com.android.systemui.screenshot.TakeScreenshotService");
Intent intent = new Intent();
intent.setComponent(cn);
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != this) {
return;
}
Messenger messenger = new Messenger(service);
Message msg = Message.obtain(null, 1);
final ServiceConnection myConn = this;
Handler h = new Handler(mHandler.getLooper()) {
@Override
public void handleMessage(Message msg) {
synchronized (mScreenshotLock) {
finishScreenshotLSS(myConn);
}
}
};
msg.replyTo = new Messenger(h);
try {
messenger.send(msg);
} catch (RemoteException e) {
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
mScreenshotConnection = conn;
mScreenshotTimeout = new Runnable() {
@Override public void run() {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) {
finishScreenshotLSS(mScreenshotConnection);
}
}
}
};
mHandler.postDelayed(mScreenshotTimeout, 10000);
}
final Runnable mScreenshotTimeout = new Runnable() {
@Override public void run() {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) {
mContext.unbindService(mScreenshotConnection);
mScreenshotConnection = null;
}
}
});
}
};
// Assume this is called from the Handler thread.
private void takeScreenshot() {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) {
return;
}
ComponentName cn = new ComponentName("com.android.systemui",
"com.android.systemui.screenshot.TakeScreenshotService");
Intent intent = new Intent();
intent.setComponent(cn);
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != this) {
return;
}
Messenger messenger = new Messenger(service);
Message msg = Message.obtain(null, 1);
final ServiceConnection myConn = this;
Handler h = new Handler(mHandler.getLooper()) {
@Override
public void handleMessage(Message msg) {
synchronized (mScreenshotLock) {
if (mScreenshotConnection == myConn) {
mContext.unbindService(mScreenshotConnection);
mScreenshotConnection = null;
mHandler.removeCallbacks(mScreenshotTimeout);
}
}
}
};
msg.replyTo = new Messenger(h);
try {
messenger.send(msg);
} catch (RemoteException e) {
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
mScreenshotConnection = conn;
mHandler.postDelayed(mScreenshotTimeout, 10000);
}
}
}
/** {@inheritDoc} */
@ -2609,28 +2655,35 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Handle special keys.
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (down) {
if (isScreenOn) {
// If the power key down was already triggered, take the screenshot
if (mPowerDownTriggered) {
// Dismiss the power-key longpress
mHandler.removeCallbacks(mPowerLongPress);
mPowerKeyHandled = true;
// Take the screenshot
takeScreenshot();
// Prevent the event from being passed through to the current activity
result &= ~ACTION_PASS_TO_USER;
break;
}
mVolumeDownTriggered = true;
}
} else {
mVolumeDownTriggered = false;
}
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_MUTE: {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if (down) {
if (isScreenOn && !mVolumeDownKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mVolumeDownKeyTriggered = true;
mVolumeDownKeyTime = event.getDownTime();
mVolumeDownKeyConsumedByScreenshotChord = false;
cancelPendingPowerKeyAction();
interceptScreenshotChord();
}
} else {
mVolumeDownKeyTriggered = false;
cancelPendingScreenshotChordAction();
}
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
if (down) {
if (isScreenOn && !mVolumeUpKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mVolumeUpKeyTriggered = true;
cancelPendingPowerKeyAction();
cancelPendingScreenshotChordAction();
}
} else {
mVolumeUpKeyTriggered = false;
cancelPendingScreenshotChordAction();
}
}
if (down) {
ITelephony telephonyService = getTelephonyService();
if (telephonyService != null) {
@ -2709,17 +2762,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
if (down) {
if (isScreenOn) {
// If the volume down key has been triggered, then just take the screenshot
if (mVolumeDownTriggered) {
// Take the screenshot
takeScreenshot();
mPowerKeyHandled = true;
// Prevent the event from being passed through to the current activity
break;
}
mPowerDownTriggered = true;
if (isScreenOn && !mPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mPowerKeyTriggered = true;
mPowerKeyTime = event.getDownTime();
interceptScreenshotChord();
}
ITelephony telephonyService = getTelephonyService();
@ -2741,12 +2788,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Log.w(TAG, "ITelephony threw RemoteException", ex);
}
}
interceptPowerKeyDown(!isScreenOn || hungUp);
interceptPowerKeyDown(!isScreenOn || hungUp
|| mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
} else {
mPowerDownTriggered = false;
if (interceptPowerKeyUp(canceled)) {
mPowerKeyTriggered = false;
cancelPendingScreenshotChordAction();
if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
}
mPendingPowerKeyUpCanceled = false;
}
break;
}

View File

@ -804,6 +804,18 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
logOutboundKeyDetailsLocked("dispatchKey - ", entry);
}
// Handle case where the policy asked us to try again later last time.
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
if (currentTime < entry->interceptKeyWakeupTime) {
if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
*nextWakeupTime = entry->interceptKeyWakeupTime;
}
return false; // wait until next wakeup
}
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
entry->interceptKeyWakeupTime = 0;
}
// Give the policy a chance to intercept the key.
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
@ -3827,14 +3839,19 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
mLock.unlock();
bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
&event, entry->policyFlags);
mLock.lock();
entry->interceptKeyResult = consumed
? KeyEntry::INTERCEPT_KEY_RESULT_SKIP
: KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
if (delay < 0) {
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
} else if (!delay) {
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
} else {
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
entry->interceptKeyWakeupTime = now() + delay;
}
entry->release();
}
@ -4156,7 +4173,8 @@ InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime,
deviceId(deviceId), source(source), action(action), flags(flags),
keyCode(keyCode), scanCode(scanCode), metaState(metaState),
repeatCount(repeatCount), downTime(downTime),
syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN),
interceptKeyWakeupTime(0) {
}
InputDispatcher::KeyEntry::~KeyEntry() {
@ -4168,6 +4186,7 @@ void InputDispatcher::KeyEntry::recycle() {
dispatchInProgress = false;
syntheticRepeat = false;
interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
interceptKeyWakeupTime = 0;
}

View File

@ -242,7 +242,7 @@ public:
virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
/* Allows the policy a chance to intercept a key before dispatching. */
virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
/* Allows the policy a chance to perform default processing for an unhandled key.
@ -481,8 +481,10 @@ private:
INTERCEPT_KEY_RESULT_UNKNOWN,
INTERCEPT_KEY_RESULT_SKIP,
INTERCEPT_KEY_RESULT_CONTINUE,
INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER,
};
InterceptKeyResult interceptKeyResult; // set based on the interception result
nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER
KeyEntry(nsecs_t eventTime,
int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,

View File

@ -75,9 +75,9 @@ private:
virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
}
virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags) {
return false;
return 0;
}
virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,

View File

@ -575,7 +575,7 @@ public class InputManager implements Watchdog.Monitor {
}
@SuppressWarnings("unused")
public boolean interceptKeyBeforeDispatching(InputWindowHandle focus,
public long interceptKeyBeforeDispatching(InputWindowHandle focus,
KeyEvent event, int policyFlags) {
return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(
focus, event, policyFlags);

View File

@ -288,7 +288,7 @@ final class InputMonitor {
/* Provides an opportunity for the window manager policy to process a key before
* ordinary dispatch. */
public boolean interceptKeyBeforeDispatching(
public long interceptKeyBeforeDispatching(
InputWindowHandle focus, KeyEvent event, int policyFlags) {
WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);

View File

@ -149,6 +149,12 @@ static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, int32_t styl
}
}
enum {
WM_ACTION_PASS_TO_USER = 1,
WM_ACTION_POKE_USER_ACTIVITY = 2,
WM_ACTION_GO_TO_SLEEP = 4,
};
// --- NativeInputManager ---
@ -199,7 +205,8 @@ public:
virtual bool isKeyRepeatEnabled();
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
virtual nsecs_t interceptKeyBeforeDispatching(
const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags);
virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
@ -819,12 +826,6 @@ void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& p
void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
uint32_t& policyFlags) {
enum {
WM_ACTION_PASS_TO_USER = 1,
WM_ACTION_POKE_USER_ACTIVITY = 2,
WM_ACTION_GO_TO_SLEEP = 4,
};
if (wmActions & WM_ACTION_GO_TO_SLEEP) {
#if DEBUG_INPUT_DISPATCHER_POLICY
LOGD("handleInterceptActions: Going to sleep.");
@ -848,14 +849,14 @@ void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
}
}
bool NativeInputManager::interceptKeyBeforeDispatching(
nsecs_t NativeInputManager::interceptKeyBeforeDispatching(
const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags) {
// Policy:
// - Ignore untrusted events and pass them along.
// - Filter normal events and trusted injected events through the window manager policy to
// handle the HOME key and the like.
bool result = false;
nsecs_t result = 0;
if (policyFlags & POLICY_FLAG_TRUSTED) {
JNIEnv* env = jniEnv();
@ -863,13 +864,19 @@ bool NativeInputManager::interceptKeyBeforeDispatching(
jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
if (keyEventObj) {
jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
jlong delayMillis = env->CallLongMethod(mCallbacksObj,
gCallbacksClassInfo.interceptKeyBeforeDispatching,
inputWindowHandleObj, keyEventObj, policyFlags);
bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
result = consumed && !error;
if (!error) {
if (delayMillis < 0) {
result = -1;
} else if (delayMillis > 0) {
result = milliseconds_to_nanoseconds(delayMillis);
}
}
} else {
LOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
}
@ -1433,7 +1440,7 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, clazz,
"interceptKeyBeforeDispatching",
"(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)Z");
"(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)J");
GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, clazz,
"dispatchUnhandledKey",