Merge "DO NOT MERGE. Improve screenshot chord debouncing. Bug: 5011907" into ics-mr0
This commit is contained in:
@ -104,23 +104,23 @@ public interface WindowManagerPolicy {
|
|||||||
*/
|
*/
|
||||||
public final static String EXTRA_HDMI_PLUGGED_STATE = "state";
|
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;
|
public final static int ACTION_PASS_TO_USER = 0x00000001;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This key event should extend the user activity timeout and turn the lights on.
|
* 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
|
* To be returned from {@link #interceptKeyBeforeQueueing}.
|
||||||
* {@link #ACTION_GO_TO_SLEEP} or {@link #ACTION_PASS_TO_USER}.
|
* 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;
|
public final static int ACTION_POKE_USER_ACTIVITY = 0x00000002;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This key event should put the device to sleep (and engage keyguard if necessary)
|
* 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
|
* To be returned from {@link #interceptKeyBeforeQueueing}.
|
||||||
* {@link #ACTION_POKE_USER_ACTIVITY} or {@link #ACTION_PASS_TO_USER}.
|
* 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;
|
public final static int ACTION_GO_TO_SLEEP = 0x00000004;
|
||||||
|
|
||||||
@ -677,10 +677,12 @@ public interface WindowManagerPolicy {
|
|||||||
* event will normally go.
|
* event will normally go.
|
||||||
* @param event The key event.
|
* @param event The key event.
|
||||||
* @param policyFlags The policy flags associated with the key.
|
* @param policyFlags The policy flags associated with the key.
|
||||||
* @return Returns true if the policy consumed the event and it should
|
* @return 0 if the key should be dispatched immediately, -1 if the key should
|
||||||
* not be further dispatched.
|
* 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
|
* Called from the input dispatcher thread when an application did not handle
|
||||||
|
@ -267,7 +267,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
WindowState mKeyguard = null;
|
WindowState mKeyguard = null;
|
||||||
KeyguardViewMediator mKeyguardMediator;
|
KeyguardViewMediator mKeyguardMediator;
|
||||||
GlobalActions mGlobalActions;
|
GlobalActions mGlobalActions;
|
||||||
volatile boolean mPowerKeyHandled;
|
volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
|
||||||
|
boolean mPendingPowerKeyUpCanceled;
|
||||||
RecentApplicationsDialog mRecentAppsDialog;
|
RecentApplicationsDialog mRecentAppsDialog;
|
||||||
Handler mHandler;
|
Handler mHandler;
|
||||||
|
|
||||||
@ -403,8 +404,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
private int mLongPressOnHomeBehavior = -1;
|
private int mLongPressOnHomeBehavior = -1;
|
||||||
|
|
||||||
// Screenshot trigger states
|
// Screenshot trigger states
|
||||||
private boolean mVolumeDownTriggered;
|
// Time to volume and power must be pressed within this interval of each other.
|
||||||
private boolean mPowerDownTriggered;
|
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;
|
ShortcutManager mShortcutManager;
|
||||||
PowerManager.WakeLock mBroadcastWakeLock;
|
PowerManager.WakeLock mBroadcastWakeLock;
|
||||||
@ -552,37 +559,64 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
if (!mPowerKeyHandled) {
|
if (!mPowerKeyHandled) {
|
||||||
mHandler.removeCallbacks(mPowerLongPress);
|
mHandler.removeCallbacks(mPowerLongPress);
|
||||||
return !canceled;
|
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() {
|
private final Runnable mPowerLongPress = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!mPowerKeyHandled) {
|
// The context isn't read
|
||||||
// The context isn't read
|
if (mLongPressOnPowerBehavior < 0) {
|
||||||
if (mLongPressOnPowerBehavior < 0) {
|
mLongPressOnPowerBehavior = mContext.getResources().getInteger(
|
||||||
mLongPressOnPowerBehavior = mContext.getResources().getInteger(
|
com.android.internal.R.integer.config_longPressOnPowerBehavior);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public boolean interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
|
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
|
||||||
final boolean keyguardOn = keyguardOn();
|
final boolean keyguardOn = keyguardOn();
|
||||||
final int keyCode = event.getKeyCode();
|
final int keyCode = event.getKeyCode();
|
||||||
final int repeatCount = event.getRepeatCount();
|
final int repeatCount = event.getRepeatCount();
|
||||||
final int metaState = event.getMetaState();
|
final int metaState = event.getMetaState();
|
||||||
|
final int flags = event.getFlags();
|
||||||
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
|
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
|
||||||
final boolean canceled = event.isCanceled();
|
final boolean canceled = event.isCanceled();
|
||||||
|
|
||||||
@ -1394,6 +1429,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
+ repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
|
+ 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
|
// First we always handle the home key here, so applications
|
||||||
// can never break it, although if keyguard is on, we do let
|
// can never break it, although if keyguard is on, we do let
|
||||||
// it handle it, because that gives us the correct 5 second
|
// it handle it, because that gives us the correct 5 second
|
||||||
@ -1425,7 +1480,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "Ignoring HOME; event canceled.");
|
Log.i(TAG, "Ignoring HOME; event canceled.");
|
||||||
}
|
}
|
||||||
return true;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a system window has focus, then it doesn't make sense
|
// 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
|
if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
|
||||||
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
|
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
|
||||||
// the "app" is keyguard, so give it the key
|
// the "app" is keyguard, so give it the key
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
|
final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
|
||||||
for (int i=0; i<typeCount; i++) {
|
for (int i=0; i<typeCount; i++) {
|
||||||
if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
|
if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
|
||||||
// don't do anything, but also don't pass it to the app
|
// 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) {
|
} else if (keyCode == KeyEvent.KEYCODE_MENU) {
|
||||||
// Hijack modified menu keys for debugging features
|
// Hijack modified menu keys for debugging features
|
||||||
final int chordBug = KeyEvent.META_SHIFT_ON;
|
final int chordBug = KeyEvent.META_SHIFT_ON;
|
||||||
@ -1465,7 +1520,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
|
if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
|
||||||
Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
|
Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
|
||||||
mContext.sendOrderedBroadcast(intent, null);
|
mContext.sendOrderedBroadcast(intent, null);
|
||||||
return true;
|
return -1;
|
||||||
} else if (SHOW_PROCESSES_ON_ALT_MENU &&
|
} else if (SHOW_PROCESSES_ON_ALT_MENU &&
|
||||||
(metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
|
(metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
|
||||||
Intent service = new Intent();
|
Intent service = new Intent();
|
||||||
@ -1480,7 +1535,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
}
|
}
|
||||||
Settings.System.putInt(
|
Settings.System.putInt(
|
||||||
res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
|
res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
|
||||||
return true;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
|
} else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
|
||||||
@ -1493,15 +1548,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
mShortcutKeyPressed = -1;
|
mShortcutKeyPressed = -1;
|
||||||
if (mConsumeShortcutKeyUp) {
|
if (mConsumeShortcutKeyUp) {
|
||||||
mConsumeShortcutKeyUp = false;
|
mConsumeShortcutKeyUp = false;
|
||||||
return true;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return 0;
|
||||||
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
|
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
|
||||||
if (down && repeatCount == 0) {
|
if (down && repeatCount == 0) {
|
||||||
showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
|
showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
|
||||||
}
|
}
|
||||||
return true;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shortcuts are invoked through Search+key, so intercept those here
|
// Shortcuts are invoked through Search+key, so intercept those here
|
||||||
@ -1531,11 +1586,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
+ "+" + KeyEvent.keyCodeToString(keyCode));
|
+ "+" + KeyEvent.keyCodeToString(keyCode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@ -1606,7 +1661,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
flags, event.getSource(), null);
|
flags, event.getSource(), null);
|
||||||
int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
|
int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
|
||||||
if ((actions & ACTION_PASS_TO_USER) != 0) {
|
if ((actions & ACTION_PASS_TO_USER) != 0) {
|
||||||
if (!interceptKeyBeforeDispatching(win, fallbackEvent, policyFlags)) {
|
long delayMillis = interceptKeyBeforeDispatching(
|
||||||
|
win, fallbackEvent, policyFlags);
|
||||||
|
if (delayMillis == 0) {
|
||||||
if (DEBUG_FALLBACK) {
|
if (DEBUG_FALLBACK) {
|
||||||
Slog.d(TAG, "Performing fallback.");
|
Slog.d(TAG, "Performing fallback.");
|
||||||
}
|
}
|
||||||
@ -2472,76 +2529,65 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
|
|
||||||
final Object mScreenshotLock = new Object();
|
final Object mScreenshotLock = new Object();
|
||||||
ServiceConnection mScreenshotConnection = null;
|
ServiceConnection mScreenshotConnection = null;
|
||||||
Runnable mScreenshotTimeout = null;
|
|
||||||
|
|
||||||
void finishScreenshotLSS(ServiceConnection conn) {
|
final Runnable mScreenshotTimeout = new Runnable() {
|
||||||
if (mScreenshotConnection == conn) {
|
@Override public void run() {
|
||||||
mContext.unbindService(conn);
|
synchronized (mScreenshotLock) {
|
||||||
mScreenshotConnection = null;
|
if (mScreenshotConnection != null) {
|
||||||
if (mScreenshotTimeout != null) {
|
mContext.unbindService(mScreenshotConnection);
|
||||||
mHandler.removeCallbacks(mScreenshotTimeout);
|
mScreenshotConnection = null;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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} */
|
/** {@inheritDoc} */
|
||||||
@ -2609,28 +2655,35 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
// Handle special keys.
|
// Handle special keys.
|
||||||
switch (keyCode) {
|
switch (keyCode) {
|
||||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
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_UP:
|
||||||
case KeyEvent.KEYCODE_VOLUME_MUTE: {
|
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) {
|
if (down) {
|
||||||
ITelephony telephonyService = getTelephonyService();
|
ITelephony telephonyService = getTelephonyService();
|
||||||
if (telephonyService != null) {
|
if (telephonyService != null) {
|
||||||
@ -2709,17 +2762,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
case KeyEvent.KEYCODE_POWER: {
|
case KeyEvent.KEYCODE_POWER: {
|
||||||
result &= ~ACTION_PASS_TO_USER;
|
result &= ~ACTION_PASS_TO_USER;
|
||||||
if (down) {
|
if (down) {
|
||||||
if (isScreenOn) {
|
if (isScreenOn && !mPowerKeyTriggered
|
||||||
// If the volume down key has been triggered, then just take the screenshot
|
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
|
||||||
if (mVolumeDownTriggered) {
|
mPowerKeyTriggered = true;
|
||||||
// Take the screenshot
|
mPowerKeyTime = event.getDownTime();
|
||||||
takeScreenshot();
|
interceptScreenshotChord();
|
||||||
mPowerKeyHandled = true;
|
|
||||||
|
|
||||||
// Prevent the event from being passed through to the current activity
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mPowerDownTriggered = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ITelephony telephonyService = getTelephonyService();
|
ITelephony telephonyService = getTelephonyService();
|
||||||
@ -2741,12 +2788,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
Log.w(TAG, "ITelephony threw RemoteException", ex);
|
Log.w(TAG, "ITelephony threw RemoteException", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
interceptPowerKeyDown(!isScreenOn || hungUp);
|
interceptPowerKeyDown(!isScreenOn || hungUp
|
||||||
|
|| mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
|
||||||
} else {
|
} else {
|
||||||
mPowerDownTriggered = false;
|
mPowerKeyTriggered = false;
|
||||||
if (interceptPowerKeyUp(canceled)) {
|
cancelPendingScreenshotChordAction();
|
||||||
|
if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
|
||||||
result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
|
result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
|
||||||
}
|
}
|
||||||
|
mPendingPowerKeyUpCanceled = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -804,6 +804,18 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
|
|||||||
logOutboundKeyDetailsLocked("dispatchKey - ", 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.
|
// Give the policy a chance to intercept the key.
|
||||||
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
|
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
|
||||||
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
|
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
|
||||||
@ -3827,14 +3839,19 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
|
|||||||
|
|
||||||
mLock.unlock();
|
mLock.unlock();
|
||||||
|
|
||||||
bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
|
nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
|
||||||
&event, entry->policyFlags);
|
&event, entry->policyFlags);
|
||||||
|
|
||||||
mLock.lock();
|
mLock.lock();
|
||||||
|
|
||||||
entry->interceptKeyResult = consumed
|
if (delay < 0) {
|
||||||
? KeyEntry::INTERCEPT_KEY_RESULT_SKIP
|
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
|
||||||
: KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
|
} 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();
|
entry->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4156,7 +4173,8 @@ InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime,
|
|||||||
deviceId(deviceId), source(source), action(action), flags(flags),
|
deviceId(deviceId), source(source), action(action), flags(flags),
|
||||||
keyCode(keyCode), scanCode(scanCode), metaState(metaState),
|
keyCode(keyCode), scanCode(scanCode), metaState(metaState),
|
||||||
repeatCount(repeatCount), downTime(downTime),
|
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() {
|
InputDispatcher::KeyEntry::~KeyEntry() {
|
||||||
@ -4168,6 +4186,7 @@ void InputDispatcher::KeyEntry::recycle() {
|
|||||||
dispatchInProgress = false;
|
dispatchInProgress = false;
|
||||||
syntheticRepeat = false;
|
syntheticRepeat = false;
|
||||||
interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
|
interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
|
||||||
|
interceptKeyWakeupTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ public:
|
|||||||
virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
|
virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
|
||||||
|
|
||||||
/* Allows the policy a chance to intercept a key before dispatching. */
|
/* 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;
|
const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
|
||||||
|
|
||||||
/* Allows the policy a chance to perform default processing for an unhandled key.
|
/* 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_UNKNOWN,
|
||||||
INTERCEPT_KEY_RESULT_SKIP,
|
INTERCEPT_KEY_RESULT_SKIP,
|
||||||
INTERCEPT_KEY_RESULT_CONTINUE,
|
INTERCEPT_KEY_RESULT_CONTINUE,
|
||||||
|
INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER,
|
||||||
};
|
};
|
||||||
InterceptKeyResult interceptKeyResult; // set based on the interception result
|
InterceptKeyResult interceptKeyResult; // set based on the interception result
|
||||||
|
nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER
|
||||||
|
|
||||||
KeyEntry(nsecs_t eventTime,
|
KeyEntry(nsecs_t eventTime,
|
||||||
int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
|
int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
|
||||||
|
@ -75,9 +75,9 @@ private:
|
|||||||
virtual void interceptMotionBeforeQueueing(nsecs_t when, 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) {
|
const KeyEvent* keyEvent, uint32_t policyFlags) {
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
|
virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
|
||||||
|
@ -575,7 +575,7 @@ public class InputManager implements Watchdog.Monitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public boolean interceptKeyBeforeDispatching(InputWindowHandle focus,
|
public long interceptKeyBeforeDispatching(InputWindowHandle focus,
|
||||||
KeyEvent event, int policyFlags) {
|
KeyEvent event, int policyFlags) {
|
||||||
return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(
|
return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(
|
||||||
focus, event, policyFlags);
|
focus, event, policyFlags);
|
||||||
|
@ -288,7 +288,7 @@ final class InputMonitor {
|
|||||||
|
|
||||||
/* Provides an opportunity for the window manager policy to process a key before
|
/* Provides an opportunity for the window manager policy to process a key before
|
||||||
* ordinary dispatch. */
|
* ordinary dispatch. */
|
||||||
public boolean interceptKeyBeforeDispatching(
|
public long interceptKeyBeforeDispatching(
|
||||||
InputWindowHandle focus, KeyEvent event, int policyFlags) {
|
InputWindowHandle focus, KeyEvent event, int policyFlags) {
|
||||||
WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
|
WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
|
||||||
return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
|
return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
|
||||||
|
@ -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 ---
|
// --- NativeInputManager ---
|
||||||
|
|
||||||
@ -199,7 +205,8 @@ public:
|
|||||||
virtual bool isKeyRepeatEnabled();
|
virtual bool isKeyRepeatEnabled();
|
||||||
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
|
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
|
||||||
virtual void interceptMotionBeforeQueueing(nsecs_t when, 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);
|
const KeyEvent* keyEvent, uint32_t policyFlags);
|
||||||
virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
|
virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
|
||||||
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
|
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,
|
void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
|
||||||
uint32_t& policyFlags) {
|
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 (wmActions & WM_ACTION_GO_TO_SLEEP) {
|
||||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||||
LOGD("handleInterceptActions: Going to sleep.");
|
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 sp<InputWindowHandle>& inputWindowHandle,
|
||||||
const KeyEvent* keyEvent, uint32_t policyFlags) {
|
const KeyEvent* keyEvent, uint32_t policyFlags) {
|
||||||
// Policy:
|
// Policy:
|
||||||
// - Ignore untrusted events and pass them along.
|
// - Ignore untrusted events and pass them along.
|
||||||
// - Filter normal events and trusted injected events through the window manager policy to
|
// - Filter normal events and trusted injected events through the window manager policy to
|
||||||
// handle the HOME key and the like.
|
// handle the HOME key and the like.
|
||||||
bool result = false;
|
nsecs_t result = 0;
|
||||||
if (policyFlags & POLICY_FLAG_TRUSTED) {
|
if (policyFlags & POLICY_FLAG_TRUSTED) {
|
||||||
JNIEnv* env = jniEnv();
|
JNIEnv* env = jniEnv();
|
||||||
|
|
||||||
@ -863,13 +864,19 @@ bool NativeInputManager::interceptKeyBeforeDispatching(
|
|||||||
jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
|
jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
|
||||||
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
|
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
|
||||||
if (keyEventObj) {
|
if (keyEventObj) {
|
||||||
jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
|
jlong delayMillis = env->CallLongMethod(mCallbacksObj,
|
||||||
gCallbacksClassInfo.interceptKeyBeforeDispatching,
|
gCallbacksClassInfo.interceptKeyBeforeDispatching,
|
||||||
inputWindowHandleObj, keyEventObj, policyFlags);
|
inputWindowHandleObj, keyEventObj, policyFlags);
|
||||||
bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
|
bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
|
||||||
android_view_KeyEvent_recycle(env, keyEventObj);
|
android_view_KeyEvent_recycle(env, keyEventObj);
|
||||||
env->DeleteLocalRef(keyEventObj);
|
env->DeleteLocalRef(keyEventObj);
|
||||||
result = consumed && !error;
|
if (!error) {
|
||||||
|
if (delayMillis < 0) {
|
||||||
|
result = -1;
|
||||||
|
} else if (delayMillis > 0) {
|
||||||
|
result = milliseconds_to_nanoseconds(delayMillis);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
|
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,
|
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, clazz,
|
||||||
"interceptKeyBeforeDispatching",
|
"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,
|
GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, clazz,
|
||||||
"dispatchUnhandledKey",
|
"dispatchUnhandledKey",
|
||||||
|
Reference in New Issue
Block a user