Merge "Fix bug in KeyButtonView key injection logic. Bug: 5299191 Bug: 5300282"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 840087c..3a06068 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -16,12 +16,10 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.animation.Animator;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.Canvas;
 import android.graphics.RectF;
@@ -29,7 +27,6 @@
 import android.os.SystemClock;
 import android.os.ServiceManager;
 import android.util.AttributeSet;
-import android.util.Slog;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.HapticFeedbackConstants;
 import android.view.IWindowManager;
@@ -40,9 +37,7 @@
 import android.view.SoundEffectConstants;
 import android.view.View;
 import android.view.ViewConfiguration;
-import android.view.ViewGroup;
 import android.widget.ImageView;
-import android.widget.RemoteViews.RemoteView;
 
 import com.android.systemui.R;
 
@@ -53,9 +48,7 @@
 
     IWindowManager mWindowManager;
     long mDownTime;
-    boolean mSending;
     int mCode;
-    int mRepeat;
     int mTouchSlop;
     Drawable mGlowBG;
     float mGlowAlpha = 0f, mGlowScale = 1f, mDrawingAlpha = 1f;
@@ -67,12 +60,7 @@
             if (isPressed()) {
                 // Slog.d("KeyButtonView", "longpressed: " + this);
                 if (mCode != 0) {
-                    mRepeat++;
-                    sendEvent(KeyEvent.ACTION_DOWN,
-                            KeyEvent.FLAG_FROM_SYSTEM
-                            | KeyEvent.FLAG_VIRTUAL_HARD_KEY
-                            | KeyEvent.FLAG_LONG_PRESS);
-
+                    sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
                     sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
                 } else {
                     // Just an old-fashioned ImageView
@@ -217,64 +205,54 @@
             case MotionEvent.ACTION_DOWN:
                 //Slog.d("KeyButtonView", "press");
                 mDownTime = SystemClock.uptimeMillis();
-                mRepeat = 0;
-                mSending = true;
                 setPressed(true);
-                sendEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY, mDownTime);
+                if (mCode != 0) {
+                    sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);
+                } else {
+                    // Provide the same haptic feedback that the system offers for virtual keys.
+                    performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+                }
                 if (mSupportsLongpress) {
                     removeCallbacks(mCheckLongPress);
                     postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
-                } else {
-                    mSending = false;
-                    sendEvent(KeyEvent.ACTION_UP,
-                            KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY, mDownTime);
-                    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
-                    playSoundEffect(SoundEffectConstants.CLICK);
                 }
                 break;
             case MotionEvent.ACTION_MOVE:
-                if (mSending) {
-                    x = (int)ev.getX();
-                    y = (int)ev.getY();
-                    setPressed(x >= -mTouchSlop
-                            && x < getWidth() + mTouchSlop
-                            && y >= -mTouchSlop
-                            && y < getHeight() + mTouchSlop);
-                }
+                x = (int)ev.getX();
+                y = (int)ev.getY();
+                setPressed(x >= -mTouchSlop
+                        && x < getWidth() + mTouchSlop
+                        && y >= -mTouchSlop
+                        && y < getHeight() + mTouchSlop);
                 break;
             case MotionEvent.ACTION_CANCEL:
                 setPressed(false);
-                if (mSending) {
-                    mSending = false;
-                    sendEvent(KeyEvent.ACTION_UP,
-                            KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY
-                                | KeyEvent.FLAG_CANCELED);
-                    if (mSupportsLongpress) {
-                        removeCallbacks(mCheckLongPress);
-                    }
+                if (mCode != 0) {
+                    sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
+                }
+                if (mSupportsLongpress) {
+                    removeCallbacks(mCheckLongPress);
                 }
                 break;
             case MotionEvent.ACTION_UP:
                 final boolean doIt = isPressed();
                 setPressed(false);
-                if (mSending) {
-                    mSending = false;
-                    final int flags = KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY;
-                    if (mSupportsLongpress) {
-                        removeCallbacks(mCheckLongPress);
-                    }
-
-                    if (mCode != 0) {
-                        if (doIt) {
-                            sendEvent(KeyEvent.ACTION_UP, flags);
-                            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
-                            playSoundEffect(SoundEffectConstants.CLICK);
-                        }
+                if (mCode != 0) {
+                    if (doIt) {
+                        sendEvent(KeyEvent.ACTION_UP, 0);
+                        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
+                        playSoundEffect(SoundEffectConstants.CLICK);
                     } else {
-                        // no key code, just a regular ImageView
-                        if (doIt) performClick();
+                        sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
                     }
+                } else {
+                    // no key code, just a regular ImageView
+                    if (doIt) {
+                        performClick();
+                    }
+                }
+                if (mSupportsLongpress) {
+                    removeCallbacks(mCheckLongPress);
                 }
                 break;
         }
@@ -287,8 +265,11 @@
     }
 
     void sendEvent(int action, int flags, long when) {
-        final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, mRepeat,
-                0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, flags, InputDevice.SOURCE_KEYBOARD);
+        final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
+        final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,
+                0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
+                flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+                InputDevice.SOURCE_KEYBOARD);
         try {
             //Slog.d(TAG, "injecting event " + ev);
             mWindowManager.injectInputEventNoWait(ev);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 86671bd..94fcb44 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -629,15 +629,6 @@
                 mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
     }
 
-    /**
-     * When a home-key longpress expires, close other system windows and launch the recent apps
-     */
-    Runnable mHomeLongPress = new Runnable() {
-        public void run() {
-            handleLongPressOnHome();
-        }
-    };
-
     private void handleLongPressOnHome() {
         // We can't initialize this in init() since the configuration hasn't been loaded yet.
         if (mLongPressOnHomeBehavior < 0) {
@@ -1418,11 +1409,6 @@
         // it handle it, because that gives us the correct 5 second
         // timeout.
         if (keyCode == KeyEvent.KEYCODE_HOME) {
-            // Clear a pending HOME longpress if the user releases Home
-            if (!down) {
-                mHandler.removeCallbacks(mHomeLongPress);
-            }
-
             // If we have released the home key, and didn't do anything else
             // while it was pressed, then it is time to go home!
             if (mHomePressed && !down) {
@@ -1470,12 +1456,15 @@
                     }
                 }
             }
-            
-            if (down && repeatCount == 0) {
-                if (!keyguardOn) {
-                    mHandler.postDelayed(mHomeLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
+
+            if (down) {
+                if (repeatCount == 0) {
+                    mHomePressed = true;
+                } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
+                    if (!keyguardOn) {
+                        handleLongPressOnHome();
+                    }
                 }
-                mHomePressed = true;
             }
             return true;
         } else if (keyCode == KeyEvent.KEYCODE_MENU) {
@@ -2518,7 +2507,8 @@
                   + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive);
         }
 
-        if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) {
+        if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
+                && event.getRepeatCount() == 0) {
             performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
         }