Improve screenshot chord debouncing.
Bug: 5011907

Introduce a 150ms delay in handling volume down keys
while waiting to see if a power key will follow.

Don't trigger the screenshot chord if both volume up and
volume down are pressed together.

Don't trigger the long-press power menu if volume keys are
also pressed.

Require the user to press both keys in the chord within
the debounce time and continue long-pressing them in order
to trigger the screenshot action.

Change-Id: I248968d37b73c09d6d08e7f62667c443eba32da0
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index f976301..7e9fba8 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -149,6 +149,12 @@
     }
 }
 
+enum {
+    WM_ACTION_PASS_TO_USER = 1,
+    WM_ACTION_POKE_USER_ACTIVITY = 2,
+    WM_ACTION_GO_TO_SLEEP = 4,
+};
+
 
 // --- NativeInputManager ---
 
@@ -199,7 +205,8 @@
     virtual bool isKeyRepeatEnabled();
     virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
     virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
-    virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
+    virtual nsecs_t interceptKeyBeforeDispatching(
+            const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags);
     virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
@@ -819,12 +826,6 @@
 
 void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
         uint32_t& policyFlags) {
-    enum {
-        WM_ACTION_PASS_TO_USER = 1,
-        WM_ACTION_POKE_USER_ACTIVITY = 2,
-        WM_ACTION_GO_TO_SLEEP = 4,
-    };
-
     if (wmActions & WM_ACTION_GO_TO_SLEEP) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
         LOGD("handleInterceptActions: Going to sleep.");
@@ -848,14 +849,14 @@
     }
 }
 
-bool NativeInputManager::interceptKeyBeforeDispatching(
+nsecs_t NativeInputManager::interceptKeyBeforeDispatching(
         const sp<InputWindowHandle>& inputWindowHandle,
         const KeyEvent* keyEvent, uint32_t policyFlags) {
     // Policy:
     // - Ignore untrusted events and pass them along.
     // - Filter normal events and trusted injected events through the window manager policy to
     //   handle the HOME key and the like.
-    bool result = false;
+    nsecs_t result = 0;
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
@@ -863,13 +864,19 @@
         jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
-            jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
+            jlong delayMillis = env->CallLongMethod(mCallbacksObj,
                     gCallbacksClassInfo.interceptKeyBeforeDispatching,
                     inputWindowHandleObj, keyEventObj, policyFlags);
             bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
             android_view_KeyEvent_recycle(env, keyEventObj);
             env->DeleteLocalRef(keyEventObj);
-            result = consumed && !error;
+            if (!error) {
+                if (delayMillis < 0) {
+                    result = -1;
+                } else if (delayMillis > 0) {
+                    result = milliseconds_to_nanoseconds(delayMillis);
+                }
+            }
         } else {
             LOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
         }
@@ -1433,7 +1440,7 @@
 
     GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, clazz,
             "interceptKeyBeforeDispatching",
-            "(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)Z");
+            "(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)J");
 
     GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, clazz,
             "dispatchUnhandledKey",