Fade out the mouse pointer after inactivity or other events.

Fades out the mouse pointer:
- after 15 seconds of inactivity normally
- after 3 seconds of inactivity in lights out mode
- after a non-modifier key down
- after a touch down

Extended the native Looper to support enqueuing time delayed
messages.  This is used by the PointerController to control
pointer fade timing.

Change-Id: I87792fea7dbe2d9376c78cf354fe3189a484d9da
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 0a50ff8..5ef234a 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -31,11 +31,13 @@
 #include <android_runtime/AndroidRuntime.h>
 
 #include <utils/Log.h>
+#include <utils/Looper.h>
 #include <utils/threads.h>
 
 #include <input/InputManager.h>
 #include <input/PointerController.h>
 
+#include <android_os_MessageQueue.h>
 #include <android_view_KeyEvent.h>
 #include <android_view_MotionEvent.h>
 #include <android_view_InputChannel.h>
@@ -136,7 +138,7 @@
     virtual ~NativeInputManager();
 
 public:
-    NativeInputManager(jobject callbacksObj);
+    NativeInputManager(jobject callbacksObj, const sp<Looper>& looper);
 
     inline sp<InputManager> getInputManager() const { return mInputManager; }
 
@@ -152,6 +154,7 @@
     void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
     void setFocusedApplication(JNIEnv* env, jobject applicationObj);
     void setInputDispatchMode(bool enabled, bool frozen);
+    void setSystemUiVisibility(int32_t visibility);
 
     /* --- InputReaderPolicyInterface implementation --- */
 
@@ -188,6 +191,7 @@
     sp<InputManager> mInputManager;
 
     jobject mCallbacksObj;
+    sp<Looper> mLooper;
 
     // Cached filtering policies.
     int32_t mFilterTouchEvents;
@@ -203,10 +207,15 @@
         int32_t displayWidth, displayHeight; // -1 when initialized
         int32_t displayOrientation;
 
+        // System UI visibility.
+        int32_t systemUiVisibility;
+
         // Pointer controller singleton, created and destroyed as needed.
         wp<PointerController> pointerController;
     } mLocked;
 
+    void updateInactivityFadeDelayLocked(const sp<PointerController>& controller);
+
     // Power manager interactions.
     bool isScreenOn();
     bool isScreenBright();
@@ -220,9 +229,10 @@
 
 
 
-NativeInputManager::NativeInputManager(jobject callbacksObj) :
-    mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), mVirtualKeyQuietTime(-1),
-    mMaxEventsPerSecond(-1) {
+NativeInputManager::NativeInputManager(jobject callbacksObj, const sp<Looper>& looper) :
+        mLooper(looper),
+        mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), mVirtualKeyQuietTime(-1),
+        mMaxEventsPerSecond(-1) {
     JNIEnv* env = jniEnv();
 
     mCallbacksObj = env->NewGlobalRef(callbacksObj);
@@ -232,6 +242,8 @@
         mLocked.displayWidth = -1;
         mLocked.displayHeight = -1;
         mLocked.displayOrientation = ROTATION_0;
+
+        mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
     }
 
     sp<EventHub> eventHub = new EventHub();
@@ -408,7 +420,7 @@
             layer = -1;
         }
 
-        controller = new PointerController(layer);
+        controller = new PointerController(mLooper, layer);
         mLocked.pointerController = controller;
 
         controller->setDisplaySize(mLocked.displayWidth, mLocked.displayHeight);
@@ -428,6 +440,8 @@
             }
             env->DeleteLocalRef(iconObj);
         }
+
+        updateInactivityFadeDelayLocked(controller);
     }
     return controller;
 }
@@ -571,6 +585,26 @@
     mInputManager->getDispatcher()->setInputDispatchMode(enabled, frozen);
 }
 
+void NativeInputManager::setSystemUiVisibility(int32_t visibility) {
+    AutoMutex _l(mLock);
+
+    if (mLocked.systemUiVisibility != visibility) {
+        mLocked.systemUiVisibility = visibility;
+
+        sp<PointerController> controller = mLocked.pointerController.promote();
+        if (controller != NULL) {
+            updateInactivityFadeDelayLocked(controller);
+        }
+    }
+}
+
+void NativeInputManager::updateInactivityFadeDelayLocked(const sp<PointerController>& controller) {
+    bool lightsOut = mLocked.systemUiVisibility & ASYSTEM_UI_VISIBILITY_STATUS_BAR_HIDDEN;
+    controller->setInactivityFadeDelay(lightsOut
+            ? PointerController::INACTIVITY_FADE_DELAY_SHORT
+            : PointerController::INACTIVITY_FADE_DELAY_NORMAL);
+}
+
 bool NativeInputManager::isScreenOn() {
     return android_server_PowerManagerService_isScreenOn();
 }
@@ -751,9 +785,10 @@
 }
 
 static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
-        jobject callbacks) {
+        jobject callbacks, jobject messageQueueObj) {
     if (gNativeInputManager == NULL) {
-        gNativeInputManager = new NativeInputManager(callbacks);
+        sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
+        gNativeInputManager = new NativeInputManager(callbacks, looper);
     } else {
         LOGE("Input manager already initialized.");
         jniThrowRuntimeException(env, "Input manager already initialized.");
@@ -972,6 +1007,15 @@
     gNativeInputManager->setInputDispatchMode(enabled, frozen);
 }
 
+static void android_server_InputManager_nativeSetSystemUiVisibility(JNIEnv* env,
+        jclass clazz, jint visibility) {
+    if (checkInputManagerUnitialized(env)) {
+        return;
+    }
+
+    gNativeInputManager->setSystemUiVisibility(visibility);
+}
+
 static jobject android_server_InputManager_nativeGetInputDevice(JNIEnv* env,
         jclass clazz, jint deviceId) {
     if (checkInputManagerUnitialized(env)) {
@@ -1079,7 +1123,7 @@
 
 static JNINativeMethod gInputManagerMethods[] = {
     /* name, signature, funcPtr */
-    { "nativeInit", "(Lcom/android/server/wm/InputManager$Callbacks;)V",
+    { "nativeInit", "(Lcom/android/server/wm/InputManager$Callbacks;Landroid/os/MessageQueue;)V",
             (void*) android_server_InputManager_nativeInit },
     { "nativeStart", "()V",
             (void*) android_server_InputManager_nativeStart },
@@ -1108,6 +1152,8 @@
             (void*) android_server_InputManager_nativeSetFocusedApplication },
     { "nativeSetInputDispatchMode", "(ZZ)V",
             (void*) android_server_InputManager_nativeSetInputDispatchMode },
+    { "nativeSetSystemUiVisibility", "(I)V",
+            (void*) android_server_InputManager_nativeSetSystemUiVisibility },
     { "nativeGetInputDevice", "(I)Landroid/view/InputDevice;",
             (void*) android_server_InputManager_nativeGetInputDevice },
     { "nativeGetInputDeviceIds", "()[I",