am c6f2b3b3: Merge "Fix policy issues when screen is off. (DO NOT MERGE)" into gingerbread

* commit 'c6f2b3b302c06b8b7b81ec7e3a43a7df1813d0e0':
  Fix policy issues when screen is off. (DO NOT MERGE)
This commit is contained in:
Jeff Brown
2010-12-23 12:43:48 -08:00
committed by Android Git Automerger
8 changed files with 266 additions and 267 deletions

View File

@ -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.

View File

@ -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(

View File

@ -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();
}
}
/**

View File

@ -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);
@ -1666,23 +1694,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.
*/
@ -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;
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 (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) {
performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
}
final boolean isWakeKey = (policyFlags
& (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 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) {
// 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;
// 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);
}
}
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;
}
}
} 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;
result &= ~ACTION_PASS_TO_USER;
}
}
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()) {
// 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)) {
// Otherwise, if "Power button ends call" is enabled,
// the Power button will hang up any current active call.
handled = hungUp = phoneServ.endCall();
// 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;
}
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;
}
}
} catch (RemoteException ex) {
Log.w(TAG, "ITelephony threw RemoteException" + ex);
if ((mEndcallBehavior
& Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
}
}
}
break;
}
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.
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.
hungUp = telephonyService.endCall();
}
} 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 (interceptPowerKeyUp(canceled)) {
result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
}
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;
}
break;
}
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;
}
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);
}
}
result &= ~ACTION_PASS_TO_USER;
}
}
} 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);
}
}
} 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;
}
} 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;
}

View File

@ -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")

View File

@ -5251,20 +5251,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.

View File

@ -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");

View File

@ -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
*/