Follow key event API changes.

We now use the new tracking and long press dispatching in the framework
to greatly simplify this code.

Change-Id: I4c0ed51dc2d07ed3bb20c64c67eede83bdb123b9
diff --git a/policy/com/android/internal/policy/impl/PhoneWindow.java b/policy/com/android/internal/policy/impl/PhoneWindow.java
index 72dec29..fac4182 100644
--- a/policy/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/com/android/internal/policy/impl/PhoneWindow.java
@@ -124,6 +124,7 @@
      * this is 0, there is no key held down.
      */
     private int mPanelChordingKey;
+    private boolean mPanelMayLongPress;
 
     private ImageView mLeftIconView;
 
@@ -155,121 +156,6 @@
 
     private TelephonyManager mTelephonyManager = null;
     
-    private boolean mSearchKeyDownReceived;
-
-    private boolean mKeycodeCallTimeoutActive = false;
-
-    private boolean mKeycodeCameraTimeoutActive = false;
-
-    static final int MSG_MENU_LONG_PRESS = 1;
-    static final int MSG_MENU_LONG_PRESS_COMPLETE = 2;
-    static final int MSG_CALL_LONG_PRESS = 3;
-    static final int MSG_CALL_LONG_PRESS_COMPLETE = 4;
-    static final int MSG_CAMERA_LONG_PRESS = 5;
-    static final int MSG_CAMERA_LONG_PRESS_COMPLETE = 6;
-    static final int MSG_SEARCH_LONG_PRESS = 7;
-    static final int MSG_SEARCH_LONG_PRESS_COMPLETE = 8;
-
-    private final Handler mKeycodeMenuTimeoutHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_MENU_LONG_PRESS: {
-                    if (mPanelChordingKey == 0) return;
-                    // Before actually doing the long press, enqueue another
-                    // message and do the processing there.  This helps if
-                    // the app isn't being responsive, and finally woke up --
-                    // if the window manager wasn't told about it processing
-                    // the down key for too long, it would enqueue the key up
-                    // at a time after the timeout of this message.  So we go
-                    // through another message, to make sure we process an up
-                    // before continuing.
-                    mKeycodeMenuTimeoutHandler.sendEmptyMessage(
-                            MSG_MENU_LONG_PRESS_COMPLETE);
-                    break;
-                }
-                case MSG_CALL_LONG_PRESS: {
-                    if (!mKeycodeCallTimeoutActive) return;
-                    // See above.
-                    mKeycodeMenuTimeoutHandler.sendEmptyMessage(
-                            MSG_CALL_LONG_PRESS_COMPLETE);
-                    break;
-                }
-                case MSG_CAMERA_LONG_PRESS: {
-                    if (!mKeycodeCameraTimeoutActive) return;
-                    // See above.
-                    Message newMessage = Message.obtain(msg);
-                    newMessage.what = MSG_CAMERA_LONG_PRESS_COMPLETE;
-                    mKeycodeMenuTimeoutHandler.sendMessage(newMessage);
-                    break;
-                }
-                case MSG_SEARCH_LONG_PRESS: {
-                    if (!mSearchKeyDownReceived) return;
-                    // See above.
-                    Message newMessage = Message.obtain(msg);
-                    newMessage.what = MSG_SEARCH_LONG_PRESS_COMPLETE;
-                    mKeycodeMenuTimeoutHandler.sendMessage(newMessage);
-                    break;
-                }
-                case MSG_MENU_LONG_PRESS_COMPLETE: {
-                    if (mPanelChordingKey == 0) return;
-                    mPanelChordingKey = 0;
-                    mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-                    InputMethodManager imm = (InputMethodManager)
-                            getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-                    if (imm != null) {
-                        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
-                    }
-                } break;
-                case MSG_CALL_LONG_PRESS_COMPLETE: {
-                    if (!mKeycodeCallTimeoutActive) return;
-                    mKeycodeCallTimeoutActive = false;
-                    mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-                    // launch the VoiceDialer
-                    Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
-                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                    try {
-                        sendCloseSystemWindows();
-                        getContext().startActivity(intent);
-                    } catch (ActivityNotFoundException e) {
-                        startCallActivity();
-                    }
-                } break;
-                case MSG_CAMERA_LONG_PRESS_COMPLETE: {
-                    if (!mKeycodeCameraTimeoutActive) return;
-                    mKeycodeCameraTimeoutActive = false;
-                    mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-                    sendCloseSystemWindows();
-                    // Broadcast an intent that the Camera button was longpressed
-                    Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
-                    intent.putExtra(Intent.EXTRA_KEY_EVENT, (KeyEvent) msg.obj);
-                    getContext().sendOrderedBroadcast(intent, null);
-                } break;
-                case MSG_SEARCH_LONG_PRESS_COMPLETE: {
-                    if (getKeyguardManager().inKeyguardRestrictedInputMode() ||
-                            !mSearchKeyDownReceived) {
-                        mSearchKeyDownReceived = false;
-                        return;
-                    }
-                    mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-                    // launch the search activity
-                    Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
-                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                    try {
-                        sendCloseSystemWindows();
-                        getContext().startActivity(intent);
-                        // Only clear this if we successfully start the
-                        // activity; otherwise we will allow the normal short
-                        // press action to be performed.
-                        mSearchKeyDownReceived = false;
-                    } catch (ActivityNotFoundException e) {
-                        // Ignore
-                    }
-                } break;
-            }
-        }
-    };
-
     public PhoneWindow(Context context) {
         super(context);
         mLayoutInflater = LayoutInflater.from(context);
@@ -649,19 +535,35 @@
      * @return Whether the key was handled.
      */
     public final boolean onKeyDownPanel(int featureId, KeyEvent event) {
-        // The panel key was pushed, so set the chording key
-        mPanelChordingKey = event.getKeyCode();
-
-        PanelFeatureState st = getPanelState(featureId, true);
-        if (!st.isOpen) {
-            if (getContext().getResources().getConfiguration().keyboard
-                    == Configuration.KEYBOARD_NOKEYS) {
-                mKeycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);
-                mKeycodeMenuTimeoutHandler.sendMessageDelayed(
-                        mKeycodeMenuTimeoutHandler.obtainMessage(MSG_MENU_LONG_PRESS),
-                        ViewConfiguration.getLongPressTimeout());
+        final int keyCode = event.getKeyCode();
+        
+        if (event.getRepeatCount() == 0) {
+            // The panel key was pushed, so set the chording key
+            mPanelChordingKey = keyCode;
+            mPanelMayLongPress = false;
+            
+            PanelFeatureState st = getPanelState(featureId, true);
+            if (!st.isOpen) {
+                if (getContext().getResources().getConfiguration().keyboard
+                        == Configuration.KEYBOARD_NOKEYS) {
+                    mPanelMayLongPress = true;
+                }
+                return preparePanel(st, event);
             }
-            return preparePanel(st, event);
+            
+        } else if (mPanelMayLongPress && mPanelChordingKey == keyCode
+                && (event.getFlags()&KeyEvent.FLAG_LONG_PRESS) != 0) {
+            // We have had a long press while in a state where this
+            // should be executed...  do it!
+            mPanelChordingKey = 0;
+            mPanelMayLongPress = false;
+            InputMethodManager imm = (InputMethodManager)
+                    getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+            if (imm != null) {
+                mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+                imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
+            }
+            
         }
 
         return false;
@@ -676,7 +578,7 @@
         // The panel key was released, so clear the chording key
         if (mPanelChordingKey != 0) {
             mPanelChordingKey = 0;
-            mKeycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);
+            mPanelMayLongPress = false;
 
             if (event.isCanceled()) {
                 return;
@@ -1218,6 +1120,11 @@
      * @see android.view.KeyEvent
      */
     protected boolean onKeyDown(int featureId, int keyCode, KeyEvent event) {
+        final KeyEvent.DispatcherState dispatcher =
+                mDecor != null ? mDecor.getKeyDispatcherState() : null;
+        //Log.i(TAG, "Key down: repeat=" + event.getRepeatCount()
+        //        + " flags=0x" + Integer.toHexString(event.getFlags()));
+        
         switch (keyCode) {
             case KeyEvent.KEYCODE_VOLUME_UP:
             case KeyEvent.KEYCODE_VOLUME_DOWN: {
@@ -1264,26 +1171,31 @@
             }
 
             case KeyEvent.KEYCODE_CAMERA: {
-                if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
+                if (getKeyguardManager().inKeyguardRestrictedInputMode()
+                        || dispatcher == null) {
                     break;
                 }
-                if (event.getRepeatCount() > 0) break;
-                mKeycodeCameraTimeoutActive = true;
-                mKeycodeMenuTimeoutHandler.removeMessages(MSG_CAMERA_LONG_PRESS);
-                Message message = mKeycodeMenuTimeoutHandler.obtainMessage(MSG_CAMERA_LONG_PRESS);
-                message.obj = event;
-                mKeycodeMenuTimeoutHandler.sendMessageDelayed(message,
-                        ViewConfiguration.getLongPressTimeout());
+                if (event.getRepeatCount() == 0) {
+                    dispatcher.startTracking(event, this);
+                } else if (event.isLongPress() && dispatcher.isTracking(event)) {
+                    dispatcher.performedLongPress(event);
+                    mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+                    sendCloseSystemWindows();
+                    // Broadcast an intent that the Camera button was longpressed
+                    Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
+                    intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
+                    getContext().sendOrderedBroadcast(intent, null);
+                }
                 return true;
             }
 
             case KeyEvent.KEYCODE_MENU: {
-                if (event.getRepeatCount() > 0) break;
                 onKeyDownPanel((featureId < 0) ? FEATURE_OPTIONS_PANEL : featureId, event);
                 return true;
             }
 
             case KeyEvent.KEYCODE_BACK: {
+                // Currently don't do anything with long presses.
                 if (event.getRepeatCount() > 0) break;
                 if (featureId < 0) break;
                 if (featureId == FEATURE_OPTIONS_PANEL) {
@@ -1300,34 +1212,55 @@
             }
 
             case KeyEvent.KEYCODE_CALL: {
-                if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
+                if (getKeyguardManager().inKeyguardRestrictedInputMode()
+                        || dispatcher == null) {
                     break;
                 }
-                if (event.getRepeatCount() > 0) break;
-                mKeycodeCallTimeoutActive = true;
-                mKeycodeMenuTimeoutHandler.removeMessages(MSG_CALL_LONG_PRESS);
-                mKeycodeMenuTimeoutHandler.sendMessageDelayed(
-                        mKeycodeMenuTimeoutHandler.obtainMessage(MSG_CALL_LONG_PRESS),
-                        ViewConfiguration.getLongPressTimeout());
+                if (event.getRepeatCount() == 0) {
+                    dispatcher.startTracking(event, this);
+                } else if (event.isLongPress() && dispatcher.isTracking(event)) {
+                    dispatcher.performedLongPress(event);
+                    mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+                    // launch the VoiceDialer
+                    Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    try {
+                        sendCloseSystemWindows();
+                        getContext().startActivity(intent);
+                    } catch (ActivityNotFoundException e) {
+                        startCallActivity();
+                    }
+                }
                 return true;
             }
 
             case KeyEvent.KEYCODE_SEARCH: {
+                if (getKeyguardManager().inKeyguardRestrictedInputMode()
+                        || dispatcher == null) {
+                    break;
+                }
                 if (event.getRepeatCount() == 0) {
-                    mSearchKeyDownReceived = true;
+                    dispatcher.startTracking(event, this);
+                } else if (event.isLongPress() && dispatcher.isTracking(event)) {
                     Configuration config = getContext().getResources().getConfiguration(); 
                     if (config.keyboard == Configuration.KEYBOARD_NOKEYS
-                            || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
-                        // If this device does not have a hardware keyboard,
-                        // or that keyboard is hidden, then we can't use the
-                        // search key for chording to perform shortcuts;
-                        // instead, we will let the user long press,
-                        mKeycodeMenuTimeoutHandler.removeMessages(MSG_SEARCH_LONG_PRESS);
-                        mKeycodeMenuTimeoutHandler.sendMessageDelayed(
-                                mKeycodeMenuTimeoutHandler.obtainMessage(MSG_SEARCH_LONG_PRESS),
-                                ViewConfiguration.getLongPressTimeout());
+                            || config.hardKeyboardHidden
+                                    == Configuration.HARDKEYBOARDHIDDEN_YES) {
+                        // launch the search activity
+                        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        try {
+                            sendCloseSystemWindows();
+                            getContext().startActivity(intent);
+                            mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+                            // Only clear this if we successfully start the
+                            // activity; otherwise we will allow the normal short
+                            // press action to be performed.
+                            dispatcher.performedLongPress(event);
+                        } catch (ActivityNotFoundException e) {
+                            // Ignore
+                        }
                     }
-                    return true;
                 }
                 break;
             }
@@ -1353,6 +1286,14 @@
      * @see android.view.KeyEvent
      */
     protected boolean onKeyUp(int featureId, int keyCode, KeyEvent event) {
+        final KeyEvent.DispatcherState dispatcher =
+                mDecor != null ? mDecor.getKeyDispatcherState() : null;
+        if (dispatcher != null) {
+            dispatcher.handleUpEvent(event);
+        }
+        //Log.i(TAG, "Key up: repeat=" + event.getRepeatCount()
+        //        + " flags=0x" + Integer.toHexString(event.getFlags()));
+        
         switch (keyCode) {
             case KeyEvent.KEYCODE_VOLUME_UP:
             case KeyEvent.KEYCODE_VOLUME_DOWN: {
@@ -1378,6 +1319,21 @@
                 return true;
             }
 
+            case KeyEvent.KEYCODE_BACK: {
+                if (featureId < 0) break;
+                if (featureId == FEATURE_OPTIONS_PANEL) {
+                    PanelFeatureState st = getPanelState(featureId, false);
+                    if (st != null && st.isInExpandedMode) {
+                        // If the user is in an expanded menu and hits back, it
+                        // should go back to the icon menu
+                        reopenMenu(true);
+                        return true;
+                    }
+                }
+                closePanel(featureId);
+                return true;
+            }
+
             case KeyEvent.KEYCODE_HEADSETHOOK:
             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
             case KeyEvent.KEYCODE_MEDIA_STOP:
@@ -1395,11 +1351,7 @@
                 if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
                     break;
                 }
-                if (event.getRepeatCount() > 0) break; // Can a key up event repeat?
-                mKeycodeMenuTimeoutHandler.removeMessages(MSG_CAMERA_LONG_PRESS);
-                if (!mKeycodeCameraTimeoutActive) break;
-                mKeycodeCameraTimeoutActive = false;
-                if (!event.isCanceled()) {
+                if (event.isTracking() && !event.isCanceled()) {
                     // Add short press behavior here if desired
                 }
                 return true;
@@ -1409,11 +1361,7 @@
                 if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
                     break;
                 }
-                if (event.getRepeatCount() > 0) break;
-                mKeycodeMenuTimeoutHandler.removeMessages(MSG_CALL_LONG_PRESS);
-                if (!mKeycodeCallTimeoutActive) break;
-                mKeycodeCallTimeoutActive = false;
-                if (!event.isCanceled()) {
+                if (event.isTracking() && !event.isCanceled()) {
                     startCallActivity();
                 }
                 return true;
@@ -1424,13 +1372,10 @@
                  * Do this in onKeyUp since the Search key is also used for
                  * chording quick launch shortcuts.
                  */
-                if (getKeyguardManager().inKeyguardRestrictedInputMode() ||
-                        !mSearchKeyDownReceived) {
-                    mSearchKeyDownReceived = false;
+                if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
                     break;
                 }
-                mSearchKeyDownReceived = false;
-                if (!event.isCanceled()) {
+                if (event.isTracking() && !event.isCanceled()) {
                     launchDefaultSearch();
                 }
                 return true;
@@ -2016,16 +1961,11 @@
         public void onWindowFocusChanged(boolean hasWindowFocus) {
             super.onWindowFocusChanged(hasWindowFocus);
 
-            // no KEYCODE_CALL events active across focus changes
-            mKeycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);
-            mKeycodeMenuTimeoutHandler.removeMessages(MSG_CALL_LONG_PRESS);
-            mKeycodeMenuTimeoutHandler.removeMessages(MSG_CAMERA_LONG_PRESS);
-            mKeycodeCallTimeoutActive = false;
-            mKeycodeCameraTimeoutActive = false;
+            mPanelMayLongPress = false;
 
             // If the user is chording a menu shortcut, release the chord since
             // this window lost focus
-            if (!hasWindowFocus && mPanelChordingKey > 0) {
+            if (!hasWindowFocus && mPanelChordingKey != 0) {
                 closePanel(FEATURE_OPTIONS_PANEL);
             }