@@ -3699,38 +3699,15 @@ private void dispatchMediaKeyEvent(KeyEvent keyEvent, boolean needWakeLock) {
36993699 }
37003700
37013701 /**
3702- * The minimum duration during which a user must press to trigger voice-based interactions
3703- */
3704- private final static int MEDIABUTTON_LONG_PRESS_DURATION_MS = 300 ;
3705- /**
3706- * The different states of the state machine to handle the launch of voice-based interactions,
3707- * stored in mVoiceButtonState.
3708- */
3709- private final static int VOICEBUTTON_STATE_IDLE = 0 ;
3710- private final static int VOICEBUTTON_STATE_DOWN = 1 ;
3711- private final static int VOICEBUTTON_STATE_DOWN_IGNORE_NEW = 2 ;
3712- /**
3713- * The different actions after state transitions on mVoiceButtonState.
3702+ * The different actions performed in response to a voice button key event.
37143703 */
37153704 private final static int VOICEBUTTON_ACTION_DISCARD_CURRENT_KEY_PRESS = 1 ;
37163705 private final static int VOICEBUTTON_ACTION_START_VOICE_INPUT = 2 ;
37173706 private final static int VOICEBUTTON_ACTION_SIMULATE_KEY_PRESS = 3 ;
37183707
37193708 private final Object mVoiceEventLock = new Object ();
3720- private int mVoiceButtonState = VOICEBUTTON_STATE_IDLE ;
3721- private long mVoiceButtonDownTime = 0 ;
3722-
3723- /**
3724- * Log an error when an unexpected action is encountered in the state machine to filter
3725- * key events.
3726- * @param keyAction the unexpected action of the key event being filtered
3727- * @param stateName the string corresponding to the state in which the error occurred
3728- */
3729- private static void logErrorForKeyAction (int keyAction , String stateName ) {
3730- Log .e (TAG , "unexpected action "
3731- + KeyEvent .actionToString (keyAction )
3732- + " in " + stateName + " state" );
3733- }
3709+ private boolean mVoiceButtonDown ;
3710+ private boolean mVoiceButtonHandled ;
37343711
37353712 /**
37363713 * Filter key events that may be used for voice-based interactions
@@ -3740,67 +3717,32 @@ private static void logErrorForKeyAction(int keyAction, String stateName) {
37403717 * is dispatched.
37413718 */
37423719 private void filterVoiceInputKeyEvent (KeyEvent keyEvent , boolean needWakeLock ) {
3720+ if (DEBUG_RC ) {
3721+ Log .v (TAG , "voice input key event: " + keyEvent + ", needWakeLock=" + needWakeLock );
3722+ }
3723+
37433724 int voiceButtonAction = VOICEBUTTON_ACTION_DISCARD_CURRENT_KEY_PRESS ;
37443725 int keyAction = keyEvent .getAction ();
37453726 synchronized (mVoiceEventLock ) {
3746- // state machine on mVoiceButtonState
3747- switch (mVoiceButtonState ) {
3748-
3749- case VOICEBUTTON_STATE_IDLE :
3750- if (keyAction == KeyEvent .ACTION_DOWN ) {
3751- mVoiceButtonDownTime = keyEvent .getDownTime ();
3752- // valid state transition
3753- mVoiceButtonState = VOICEBUTTON_STATE_DOWN ;
3754- } else if (keyAction == KeyEvent .ACTION_UP ) {
3755- // no state transition
3756- // action is still VOICEBUTTON_ACTION_DISCARD_CURRENT_KEY_PRESS
3757- } else {
3758- logErrorForKeyAction (keyAction , "VOICEBUTTON_STATE_IDLE" );
3759- }
3760- break ;
3761-
3762- case VOICEBUTTON_STATE_DOWN :
3763- if ((keyEvent .getEventTime () - mVoiceButtonDownTime )
3764- >= MEDIABUTTON_LONG_PRESS_DURATION_MS ) {
3765- // press was long enough, start voice-based interactions, regardless of
3766- // whether this was a DOWN or UP key event
3767- voiceButtonAction = VOICEBUTTON_ACTION_START_VOICE_INPUT ;
3768- if (keyAction == KeyEvent .ACTION_UP ) {
3769- // done tracking the key press, so transition back to idle state
3770- mVoiceButtonState = VOICEBUTTON_STATE_IDLE ;
3771- } else if (keyAction == KeyEvent .ACTION_DOWN ) {
3772- // no need to observe the upcoming key events
3773- mVoiceButtonState = VOICEBUTTON_STATE_DOWN_IGNORE_NEW ;
3774- } else {
3775- logErrorForKeyAction (keyAction , "VOICEBUTTON_STATE_DOWN" );
3776- }
3777- } else {
3778- if (keyAction == KeyEvent .ACTION_UP ) {
3779- // press wasn't long enough, simulate complete key press
3780- voiceButtonAction = VOICEBUTTON_ACTION_SIMULATE_KEY_PRESS ;
3781- // not tracking the key press anymore, so transition back to idle state
3782- mVoiceButtonState = VOICEBUTTON_STATE_IDLE ;
3783- } else if (keyAction == KeyEvent .ACTION_DOWN ) {
3784- // no state transition
3785- // action is still VOICEBUTTON_ACTION_DISCARD_CURRENT_KEY_PRESS
3786- } else {
3787- logErrorForKeyAction (keyAction , "VOICEBUTTON_STATE_DOWN" );
3788- }
3789- }
3790- break ;
3791-
3792- case VOICEBUTTON_STATE_DOWN_IGNORE_NEW :
3793- if (keyAction == KeyEvent .ACTION_UP ) {
3794- // done tracking the key press, so transition back to idle state
3795- mVoiceButtonState = VOICEBUTTON_STATE_IDLE ;
3796- // action is still VOICEBUTTON_ACTION_DISCARD_CURRENT_KEY_PRESS
3797- } else if (keyAction == KeyEvent .ACTION_DOWN ) {
3798- // no state transition: we've already launched voice-based interactions
3799- // action is still VOICEBUTTON_ACTION_DISCARD_CURRENT_KEY_PRESS
3800- } else {
3801- logErrorForKeyAction (keyAction , "VOICEBUTTON_STATE_DOWN_IGNORE_NEW" );
3727+ if (keyAction == KeyEvent .ACTION_DOWN ) {
3728+ if (keyEvent .getRepeatCount () == 0 ) {
3729+ // initial down
3730+ mVoiceButtonDown = true ;
3731+ mVoiceButtonHandled = false ;
3732+ } else if (mVoiceButtonDown && !mVoiceButtonHandled
3733+ && (keyEvent .getFlags () & KeyEvent .FLAG_LONG_PRESS ) != 0 ) {
3734+ // long-press, start voice-based interactions
3735+ mVoiceButtonHandled = true ;
3736+ voiceButtonAction = VOICEBUTTON_ACTION_START_VOICE_INPUT ;
3737+ }
3738+ } else if (keyAction == KeyEvent .ACTION_UP ) {
3739+ if (mVoiceButtonDown ) {
3740+ // voice button up
3741+ mVoiceButtonDown = false ;
3742+ if (!mVoiceButtonHandled && !keyEvent .isCanceled ()) {
3743+ voiceButtonAction = VOICEBUTTON_ACTION_SIMULATE_KEY_PRESS ;
38023744 }
3803- break ;
3745+ }
38043746 }
38053747 }//synchronized (mVoiceEventLock)
38063748
0 commit comments