diff options
8 files changed, 256 insertions, 257 deletions
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 1fd31a3..1a341e1 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -544,16 +544,18 @@ public interface WindowManagerPolicy { * Generally, it's best to keep as little as possible in the queue thread * because it's the most fragile. * @param whenNanos The event time in uptime nanoseconds. + * @param action The key event action. + * @param flags The key event flags. * @param keyCode The key code. - * @param down True if the key is down. + * @param scanCode The key's scan code. * @param policyFlags The policy flags associated with the key. * @param isScreenOn True if the screen is already on * * @return The bitwise or of the {@link #ACTION_PASS_TO_USER}, * {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags. */ - public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, int policyFlags, - boolean isScreenOn); + public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags, + int keyCode, int scanCode, int policyFlags, boolean isScreenOn); /** * Called from the input dispatcher thread before a key is dispatched to a window. @@ -571,6 +573,7 @@ public interface WindowManagerPolicy { * @param action The key event action. * @param flags The key event flags. * @param keyCode The key code. + * @param scanCode The key's scan code. * @param metaState bit mask of meta keys that are held. * @param repeatCount Number of times a key down has repeated. * @param policyFlags The policy flags associated with the key. @@ -578,7 +581,7 @@ public interface WindowManagerPolicy { * not be further dispatched. */ public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags, - int keyCode, int metaState, int repeatCount, int policyFlags); + int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags); /** * Called when layout of the windows is about to start. diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp index 28ccc43..421ad663 100644 --- a/libs/ui/InputDispatcher.cpp +++ b/libs/ui/InputDispatcher.cpp @@ -1405,8 +1405,13 @@ String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) { int32_t eventType = POWER_MANAGER_BUTTON_EVENT; - if (eventEntry->type == EventEntry::TYPE_MOTION) { + switch (eventEntry->type) { + case EventEntry::TYPE_MOTION: { const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry); + if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) { + return; + } + if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) { switch (motionEntry->action) { case AMOTION_EVENT_ACTION_DOWN: @@ -1424,6 +1429,15 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) { break; } } + break; + } + case EventEntry::TYPE_KEY: { + const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry); + if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) { + return; + } + break; + } } CommandEntry* commandEntry = postCommandLocked( diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index a5ef1fa..635b7d3 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -333,7 +333,12 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM mSelector.setRightHintText(mSilentMode ? R.string.lockscreen_sound_on_label : R.string.lockscreen_sound_off_label); } - mCallback.pokeWakelock(); + // Don't poke the wake lock when returning to a state where the handle is + // not grabbed since that can happen when the system (instead of the user) + // cancels the grab. + if (grabbedState != SlidingTab.OnTriggerListener.NO_HANDLE) { + mCallback.pokeWakelock(); + } } /** diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 43936a4..92c41d8 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -61,6 +61,7 @@ import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.IWindowManager; import android.view.InputChannel; +import android.view.InputDevice; import android.view.InputQueue; import android.view.InputHandler; import android.view.KeyEvent; @@ -204,7 +205,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowState mKeyguard = null; KeyguardViewMediator mKeyguardMediator; GlobalActions mGlobalActions; - boolean mShouldTurnOffOnKeyUp; + volatile boolean mPowerKeyHandled; RecentApplicationsDialog mRecentAppsDialog; Handler mHandler; @@ -456,12 +457,31 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - Runnable mPowerLongPress = new Runnable() { + private void interceptPowerKeyDown(boolean handled) { + mPowerKeyHandled = handled; + if (!handled) { + mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout()); + } + } + + private boolean interceptPowerKeyUp(boolean canceled) { + if (!mPowerKeyHandled) { + mHandler.removeCallbacks(mPowerLongPress); + return !canceled; + } else { + mPowerKeyHandled = true; + return false; + } + } + + private final Runnable mPowerLongPress = new Runnable() { public void run() { - mShouldTurnOffOnKeyUp = false; - performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); - sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); - showGlobalActionsDialog(); + if (!mPowerKeyHandled) { + mPowerKeyHandled = true; + performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); + sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); + showGlobalActionsDialog(); + } } }; @@ -1041,12 +1061,22 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.anim.lock_screen_behind_enter); } - static ITelephony getPhoneInterface() { - return ITelephony.Stub.asInterface(ServiceManager.checkService(Context.TELEPHONY_SERVICE)); + static ITelephony getTelephonyService() { + ITelephony telephonyService = ITelephony.Stub.asInterface( + ServiceManager.checkService(Context.TELEPHONY_SERVICE)); + if (telephonyService == null) { + Log.w(TAG, "Unable to find ITelephony interface."); + } + return telephonyService; } - static IAudioService getAudioInterface() { - return IAudioService.Stub.asInterface(ServiceManager.checkService(Context.AUDIO_SERVICE)); + static IAudioService getAudioService() { + IAudioService audioService = IAudioService.Stub.asInterface( + ServiceManager.checkService(Context.AUDIO_SERVICE)); + if (audioService == null) { + Log.w(TAG, "Unable to find IAudioService interface."); + } + return audioService; } boolean keyguardOn() { @@ -1061,7 +1091,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags, - int keyCode, int metaState, int repeatCount, int policyFlags) { + int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags) { final boolean keyguardOn = keyguardOn(); final boolean down = (action == KeyEvent.ACTION_DOWN); final boolean canceled = ((flags & KeyEvent.FLAG_CANCELED) != 0); @@ -1094,11 +1124,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { // and his ONLY options are to answer or reject the call.) boolean incomingRinging = false; try { - ITelephony phoneServ = getPhoneInterface(); - if (phoneServ != null) { - incomingRinging = phoneServ.isRinging(); - } else { - Log.w(TAG, "Unable to find ITelephony interface"); + ITelephony telephonyService = getTelephonyService(); + if (telephonyService != null) { + incomingRinging = telephonyService.isRinging(); } } catch (RemoteException ex) { Log.w(TAG, "RemoteException from getPhoneInterface()", ex); @@ -1667,23 +1695,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } /** - * @return Whether a telephone call is in progress right now. - */ - boolean isInCall() { - final ITelephony phone = getPhoneInterface(); - if (phone == null) { - Log.w(TAG, "couldn't get ITelephony reference"); - return false; - } - try { - return phone.isOffhook(); - } catch (RemoteException e) { - Log.w(TAG, "ITelephony.isOffhhook threw RemoteException " + e); - return false; - } - } - - /** * @return Whether music is being played right now. */ boolean isMusicActive() { @@ -1700,9 +1711,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { * @param keycode */ void handleVolumeKey(int stream, int keycode) { - final IAudioService audio = getAudioInterface(); - if (audio == null) { - Log.w(TAG, "handleVolumeKey: couldn't get IAudioService reference"); + IAudioService audioService = getAudioService(); + if (audioService == null) { return; } try { @@ -1710,7 +1720,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // during the call, but we do it as a precaution for the rare possibility // that the music stops right before we call this mBroadcastWakeLock.acquire(); - audio.adjustStreamVolume(stream, + audioService.adjustStreamVolume(stream, keycode == KeyEvent.KEYCODE_VOLUME_UP ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER, @@ -1721,39 +1731,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { mBroadcastWakeLock.release(); } } - - static boolean isMediaKey(int code) { - if (code == KeyEvent.KEYCODE_HEADSETHOOK || - code == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || - code == KeyEvent.KEYCODE_MEDIA_STOP || - code == KeyEvent.KEYCODE_MEDIA_NEXT || - code == KeyEvent.KEYCODE_MEDIA_PREVIOUS || - code == KeyEvent.KEYCODE_MEDIA_REWIND || - code == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) { - return true; - } - return false; - } /** {@inheritDoc} */ @Override - public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, - int policyFlags, boolean isScreenOn) { - int result = ACTION_PASS_TO_USER; - - if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) { - performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); - } - - final boolean isWakeKey = (policyFlags - & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; + public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags, + int keyCode, int scanCode, int policyFlags, boolean isScreenOn) { + final boolean down = action == KeyEvent.ACTION_DOWN; + final boolean canceled = (flags & KeyEvent.FLAG_CANCELED) != 0; - // If the key is injected, pretend that the screen is on and don't let the - // device go to sleep. This feature is mainly used for testing purposes. final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; - if (isInjected) { - isScreenOn = true; - } // If screen is off then we treat the case where the keyguard is open but hidden // the same as if it were open and in front. @@ -1768,202 +1754,192 @@ public class PhoneWindowManager implements WindowManagerPolicy { + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive); } - if (keyguardActive) { - if (isScreenOn) { - // when the screen is on, always give the event to the keyguard - result |= ACTION_PASS_TO_USER; - } else { - // otherwise, don't pass it to the user - result &= ~ACTION_PASS_TO_USER; + if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) { + performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); + } - if (isWakeKey && down) { - - // tell the mediator about a wake key, it may decide to - // turn on the screen depending on whether the key is - // appropriate. - if (!mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode) - && (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN - || keyCode == KeyEvent.KEYCODE_VOLUME_UP)) { - // when keyguard is showing and screen off, we need - // to handle the volume key for calls and music here - if (isInCall()) { - handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode); - } else if (isMusicActive()) { - handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode); + // Basic policy based on screen state and keyguard. + // FIXME: This policy isn't quite correct. We shouldn't care whether the screen + // is on or off, really. We should care about whether the device is in an + // interactive state or is in suspend pretending to be "off". + // The primary screen might be turned off due to proximity sensor or + // because we are presenting media on an auxiliary screen or remotely controlling + // the device some other way (which is why we have an exemption here for injected + // events). + int result; + if (isScreenOn || isInjected) { + // When the screen is on or if the key is injected pass the key to the application. + result = ACTION_PASS_TO_USER; + } else { + // When the screen is off and the key is not injected, determine whether + // to wake the device but don't pass the key to the application. + result = 0; + + final boolean isWakeKey = (policyFlags + & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; + if (down && isWakeKey) { + if (keyguardActive) { + // If the keyguard is showing, let it decide what to do with the wake key. + mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode); + } else { + // Otherwise, wake the device ourselves. + result |= ACTION_POKE_USER_ACTIVITY; + } + } + } + + // Handle special keys. + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_VOLUME_UP: { + if (down) { + ITelephony telephonyService = getTelephonyService(); + if (telephonyService != null) { + try { + if (telephonyService.isRinging()) { + // If an incoming call is ringing, either VOLUME key means + // "silence ringer". We handle these keys here, rather than + // in the InCallScreen, to make sure we'll respond to them + // even if the InCallScreen hasn't come to the foreground yet. + // Look for the DOWN event here, to agree with the "fallback" + // behavior in the InCallScreen. + Log.i(TAG, "interceptKeyBeforeQueueing:" + + " VOLUME key-down while ringing: Silence ringer!"); + + // Silence the ringer. (It's safe to call this + // even if the ringer has already been silenced.) + telephonyService.silenceRinger(); + + // And *don't* pass this key thru to the current activity + // (which is probably the InCallScreen.) + result &= ~ACTION_PASS_TO_USER; + break; + } + if (telephonyService.isOffhook() + && (result & ACTION_PASS_TO_USER) == 0) { + // If we are in call but we decided not to pass the key to + // the application, handle the volume change here. + handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode); + break; + } + } catch (RemoteException ex) { + Log.w(TAG, "ITelephony threw RemoteException", ex); } } + + if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) { + // If music is playing but we decided not to pass the key to the + // application, handle the volume change here. + handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode); + break; + } } + break; } - } else if (!isScreenOn) { - // If we are in-call with screen off and keyguard is not showing, - // then handle the volume key ourselves. - // This is necessary because the phone app will disable the keyguard - // when the proximity sensor is in use. - if (isInCall() && - (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN - || keyCode == KeyEvent.KEYCODE_VOLUME_UP)) { - result &= ~ACTION_PASS_TO_USER; - handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode); - } - if (isWakeKey) { - // a wake key has a sole purpose of waking the device; don't pass - // it to the user - result |= ACTION_POKE_USER_ACTIVITY; + + case KeyEvent.KEYCODE_ENDCALL: { result &= ~ACTION_PASS_TO_USER; + if (down) { + ITelephony telephonyService = getTelephonyService(); + boolean hungUp = false; + if (telephonyService != null) { + try { + hungUp = telephonyService.endCall(); + } catch (RemoteException ex) { + Log.w(TAG, "ITelephony threw RemoteException", ex); + } + } + interceptPowerKeyDown(!isScreenOn || hungUp); + } else { + if (interceptPowerKeyUp(canceled)) { + if ((mEndcallBehavior + & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { + if (goHome()) { + break; + } + } + if ((mEndcallBehavior + & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { + result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP; + } + } + } + break; } - } - if (keyCode == KeyEvent.KEYCODE_ENDCALL - || keyCode == KeyEvent.KEYCODE_POWER) { - if (down) { - boolean handled = false; - boolean hungUp = false; - // key repeats are generated by the window manager, and we don't see them - // here, so unless the driver is doing something it shouldn't be, we know - // this is the real press event. - ITelephony phoneServ = getPhoneInterface(); - if (phoneServ != null) { - try { - if (keyCode == KeyEvent.KEYCODE_ENDCALL) { - handled = hungUp = phoneServ.endCall(); - } else if (keyCode == KeyEvent.KEYCODE_POWER) { - if (phoneServ.isRinging()) { + case KeyEvent.KEYCODE_POWER: { + result &= ~ACTION_PASS_TO_USER; + if (down) { + ITelephony telephonyService = getTelephonyService(); + boolean hungUp = false; + if (telephonyService != null) { + try { + if (telephonyService.isRinging()) { // Pressing Power while there's a ringing incoming // call should silence the ringer. - phoneServ.silenceRinger(); - handled = true; - } else if (phoneServ.isOffhook() && - ((mIncallPowerBehavior - & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) - != 0)) { + telephonyService.silenceRinger(); + } else if ((mIncallPowerBehavior + & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 + && telephonyService.isOffhook()) { // Otherwise, if "Power button ends call" is enabled, // the Power button will hang up any current active call. - handled = hungUp = phoneServ.endCall(); + hungUp = telephonyService.endCall(); } + } catch (RemoteException ex) { + Log.w(TAG, "ITelephony threw RemoteException", ex); } - } catch (RemoteException ex) { - Log.w(TAG, "ITelephony threw RemoteException" + ex); } + interceptPowerKeyDown(!isScreenOn || hungUp); } else { - Log.w(TAG, "!!! Unable to find ITelephony interface !!!"); - } - - if (!isScreenOn - || (handled && keyCode != KeyEvent.KEYCODE_POWER) - || (handled && hungUp && keyCode == KeyEvent.KEYCODE_POWER)) { - mShouldTurnOffOnKeyUp = false; - } else { - // Only try to turn off the screen if we didn't already hang up. - mShouldTurnOffOnKeyUp = true; - mHandler.postDelayed(mPowerLongPress, - ViewConfiguration.getGlobalActionKeyTimeout()); - result &= ~ACTION_PASS_TO_USER; - } - } else { - mHandler.removeCallbacks(mPowerLongPress); - if (mShouldTurnOffOnKeyUp) { - mShouldTurnOffOnKeyUp = false; - boolean gohome, sleeps; - if (keyCode == KeyEvent.KEYCODE_ENDCALL) { - gohome = (mEndcallBehavior - & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0; - sleeps = (mEndcallBehavior - & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0; - } else { - gohome = false; - sleeps = true; - } - if (keyguardActive - || (sleeps && !gohome) - || (gohome && !goHome() && sleeps)) { - // They must already be on the keyguard or home screen, - // go to sleep instead unless the event was injected. - if (!isInjected) { - Log.d(TAG, "I'm tired mEndcallBehavior=0x" - + Integer.toHexString(mEndcallBehavior)); - result &= ~ACTION_POKE_USER_ACTIVITY; - result |= ACTION_GO_TO_SLEEP; - } + if (interceptPowerKeyUp(canceled)) { + result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP; } - result &= ~ACTION_PASS_TO_USER; } + break; } - } else if (isMediaKey(keyCode)) { - // This key needs to be handled even if the screen is off. - // If others need to be handled while it's off, this is a reasonable - // pattern to follow. - if ((result & ACTION_PASS_TO_USER) == 0) { - // Only do this if we would otherwise not pass it to the user. In that - // case, the PhoneWindow class will do the same thing, except it will - // only do it if the showing app doesn't process the key on its own. - long when = whenNanos / 1000000; - KeyEvent keyEvent = new KeyEvent(when, when, - down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP, - keyCode, 0); - mBroadcastWakeLock.acquire(); - mHandler.post(new PassHeadsetKey(keyEvent)); - } - } else if (keyCode == KeyEvent.KEYCODE_CALL) { - // If an incoming call is ringing, answer it! - // (We handle this key here, rather than in the InCallScreen, to make - // sure we'll respond to the key even if the InCallScreen hasn't come to - // the foreground yet.) - - // We answer the call on the DOWN event, to agree with - // the "fallback" behavior in the InCallScreen. - if (down) { - try { - ITelephony phoneServ = getPhoneInterface(); - if (phoneServ != null) { - if (phoneServ.isRinging()) { - Log.i(TAG, "interceptKeyTq:" - + " CALL key-down while ringing: Answer the call!"); - phoneServ.answerRingingCall(); - - // And *don't* pass this key thru to the current activity - // (which is presumably the InCallScreen.) - result &= ~ACTION_PASS_TO_USER; - } - } else { - Log.w(TAG, "CALL button: Unable to find ITelephony interface"); - } - } catch (RemoteException ex) { - Log.w(TAG, "CALL button: RemoteException from getPhoneInterface()", ex); + + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + case KeyEvent.KEYCODE_MEDIA_STOP: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + case KeyEvent.KEYCODE_MEDIA_REWIND: + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { + if ((result & ACTION_PASS_TO_USER) == 0) { + // Only do this if we would otherwise not pass it to the user. In that + // case, the PhoneWindow class will do the same thing, except it will + // only do it if the showing app doesn't process the key on its own. + long when = whenNanos / 1000000; + KeyEvent keyEvent = new KeyEvent(when, when, action, keyCode, 0, 0, + 0, scanCode, flags, InputDevice.SOURCE_KEYBOARD); + mBroadcastWakeLock.acquire(); + mHandler.post(new PassHeadsetKey(keyEvent)); } + break; } - } else if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) - || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) { - // If an incoming call is ringing, either VOLUME key means - // "silence ringer". We handle these keys here, rather than - // in the InCallScreen, to make sure we'll respond to them - // even if the InCallScreen hasn't come to the foreground yet. - - // Look for the DOWN event here, to agree with the "fallback" - // behavior in the InCallScreen. - if (down) { - try { - ITelephony phoneServ = getPhoneInterface(); - if (phoneServ != null) { - if (phoneServ.isRinging()) { - Log.i(TAG, "interceptKeyTq:" - + " VOLUME key-down while ringing: Silence ringer!"); - // Silence the ringer. (It's safe to call this - // even if the ringer has already been silenced.) - phoneServ.silenceRinger(); - - // And *don't* pass this key thru to the current activity - // (which is probably the InCallScreen.) - result &= ~ACTION_PASS_TO_USER; + + case KeyEvent.KEYCODE_CALL: { + if (down) { + ITelephony telephonyService = getTelephonyService(); + if (telephonyService != null) { + try { + if (telephonyService.isRinging()) { + Log.i(TAG, "interceptKeyBeforeQueueing:" + + " CALL key-down while ringing: Answer the call!"); + telephonyService.answerRingingCall(); + + // And *don't* pass this key thru to the current activity + // (which is presumably the InCallScreen.) + result &= ~ACTION_PASS_TO_USER; + } + } catch (RemoteException ex) { + Log.w(TAG, "ITelephony threw RemoteException", ex); } - } else { - Log.w(TAG, "VOLUME button: Unable to find ITelephony interface"); } - } catch (RemoteException ex) { - Log.w(TAG, "VOLUME button: RemoteException from getPhoneInterface()", ex); } + break; } } - return result; } diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java index df41264..b44fe00 100644 --- a/services/java/com/android/server/InputManager.java +++ b/services/java/com/android/server/InputManager.java @@ -379,17 +379,18 @@ public class InputManager { } @SuppressWarnings("unused") - public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, - int policyFlags, boolean isScreenOn) { + public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags, + int keyCode, int scanCode, int policyFlags, boolean isScreenOn) { return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing( - whenNanos, keyCode, down, policyFlags, isScreenOn); + whenNanos, action, flags, keyCode, scanCode, policyFlags, isScreenOn); } @SuppressWarnings("unused") public boolean interceptKeyBeforeDispatching(InputChannel focus, int action, - int flags, int keyCode, int metaState, int repeatCount, int policyFlags) { + int flags, int keyCode, int scanCode, int metaState, int repeatCount, + int policyFlags) { return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(focus, - action, flags, keyCode, metaState, repeatCount, policyFlags); + action, flags, keyCode, scanCode, metaState, repeatCount, policyFlags); } @SuppressWarnings("unused") diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 10cceac..f28bae0 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -5250,20 +5250,20 @@ public class WindowManagerService extends IWindowManager.Stub /* Provides an opportunity for the window manager policy to intercept early key * processing as soon as the key has been read from the device. */ - public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, - int policyFlags, boolean isScreenOn) { - return mPolicy.interceptKeyBeforeQueueing(whenNanos, - keyCode, down, policyFlags, isScreenOn); + public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags, + int keyCode, int scanCode, int policyFlags, boolean isScreenOn) { + return mPolicy.interceptKeyBeforeQueueing(whenNanos, action, flags, + keyCode, scanCode, policyFlags, isScreenOn); } /* Provides an opportunity for the window manager policy to process a key before * ordinary dispatch. */ public boolean interceptKeyBeforeDispatching(InputChannel focus, - int action, int flags, int keyCode, int metaState, int repeatCount, + int action, int flags, int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags) { WindowState windowState = getWindowStateForInputChannel(focus); return mPolicy.interceptKeyBeforeDispatching(windowState, action, flags, - keyCode, metaState, repeatCount, policyFlags); + keyCode, scanCode, metaState, repeatCount, policyFlags); } /* Called when the current input focus changes. diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index 1bd1874..693d630 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -857,7 +857,7 @@ void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when, JNIEnv* env = jniEnv(); jint wmActions = env->CallIntMethod(mCallbacksObj, gCallbacksClassInfo.interceptKeyBeforeQueueing, - when, keyCode, action == AKEY_EVENT_ACTION_DOWN, policyFlags, isScreenOn); + when, action, flags, keyCode, scanCode, policyFlags, isScreenOn); if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { wmActions = 0; } @@ -926,7 +926,7 @@ bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& i jboolean consumed = env->CallBooleanMethod(mCallbacksObj, gCallbacksClassInfo.interceptKeyBeforeDispatching, inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(), - keyEvent->getKeyCode(), keyEvent->getMetaState(), + keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(), keyEvent->getRepeatCount(), policyFlags); bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching"); @@ -1337,10 +1337,10 @@ int register_android_server_InputManager(JNIEnv* env) { "notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J"); GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz, - "interceptKeyBeforeQueueing", "(JIZIZ)I"); + "interceptKeyBeforeQueueing", "(JIIIIIZ)I"); GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz, - "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z"); + "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIIII)Z"); GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz, "checkInjectEventsPermission", "(II)Z"); diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 2328717..53f4eb7 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -66,7 +66,7 @@ interface ITelephony { boolean showCallScreenWithDialpad(boolean showDialpad); /** - * End call or go to the Home screen + * End call if there is a call in progress, otherwise does nothing. * * @return whether it hung up */ |