Initial checkin of spot presentation for touchpad gestures. (DO NOT MERGE)

Added a new PointerIcon API (hidden for now) for loading
pointer icons.

Fixed a starvation problem in the native Looper's sendMessage
implementation which caused new messages to be posted ahead
of old messages sent with sendMessageDelayed.

Redesigned the touch pad gestures to be defined in terms of
more fluid finger / spot movements.  The objective is to reinforce
the natural mapping between fingers and spots which means there
must not be any discontinuities in spot motion relative to
the fingers.

Removed the SpotController stub and folded its responsibilities
into PointerController.

Change-Id: Ib647dbd7a57a7f30dd9c6e2c260df51d7bbdd18e
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 7985fab..dde4776 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -36,13 +36,13 @@
 
 #include <input/InputManager.h>
 #include <input/PointerController.h>
-#include <input/SpotController.h>
 #include <input/SpriteController.h>
 
 #include <android_os_MessageQueue.h>
 #include <android_view_KeyEvent.h>
 #include <android_view_MotionEvent.h>
 #include <android_view_InputChannel.h>
+#include <android_view_PointerIcon.h>
 #include <android/graphics/GraphicsJNI.h>
 
 #include "com_android_server_PowerManagerService.h"
@@ -104,14 +104,6 @@
     jfieldID navigation;
 } gConfigurationClassInfo;
 
-static struct {
-    jclass clazz;
-
-    jfieldID bitmap;
-    jfieldID hotSpotX;
-    jfieldID hotSpotY;
-} gPointerIconClassInfo;
-
 
 // --- Global functions ---
 
@@ -133,17 +125,30 @@
             getInputWindowHandleObjLocalRef(env);
 }
 
+static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, int32_t style,
+        SpriteIcon* outSpriteIcon) {
+    PointerIcon pointerIcon;
+    status_t status = android_view_PointerIcon_loadSystemIcon(env,
+            contextObj, style, &pointerIcon);
+    if (!status) {
+        pointerIcon.bitmap.copyTo(&outSpriteIcon->bitmap, SkBitmap::kARGB_8888_Config);
+        outSpriteIcon->hotSpotX = pointerIcon.hotSpotX;
+        outSpriteIcon->hotSpotY = pointerIcon.hotSpotY;
+    }
+}
+
 
 // --- NativeInputManager ---
 
 class NativeInputManager : public virtual RefBase,
     public virtual InputReaderPolicyInterface,
-    public virtual InputDispatcherPolicyInterface {
+    public virtual InputDispatcherPolicyInterface,
+    public virtual PointerControllerPolicyInterface {
 protected:
     virtual ~NativeInputManager();
 
 public:
-    NativeInputManager(jobject callbacksObj, const sp<Looper>& looper);
+    NativeInputManager(jobject contextObj, jobject callbacksObj, const sp<Looper>& looper);
 
     inline sp<InputManager> getInputManager() const { return mInputManager; }
 
@@ -170,7 +175,6 @@
     virtual nsecs_t getVirtualKeyQuietTime();
     virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
     virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
-    virtual sp<SpotControllerInterface> obtainSpotController(int32_t deviceId);
 
     /* --- InputDispatcherPolicyInterface implementation --- */
 
@@ -193,9 +197,14 @@
     virtual bool checkInjectEventsPermissionNonReentrant(
             int32_t injectorPid, int32_t injectorUid);
 
+    /* --- PointerControllerPolicyInterface implementation --- */
+
+    virtual void loadPointerResources(PointerResources* outResources);
+
 private:
     sp<InputManager> mInputManager;
 
+    jobject mContextObj;
     jobject mCallbacksObj;
     sp<Looper> mLooper;
 
@@ -227,7 +236,7 @@
         wp<PointerController> pointerController;
     } mLocked;
 
-    void updateInactivityFadeDelayLocked(const sp<PointerController>& controller);
+    void updateInactivityTimeoutLocked(const sp<PointerController>& controller);
     void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
     void ensureSpriteControllerLocked();
 
@@ -244,13 +253,15 @@
 
 
 
-NativeInputManager::NativeInputManager(jobject callbacksObj, const sp<Looper>& looper) :
+NativeInputManager::NativeInputManager(jobject contextObj,
+        jobject callbacksObj, const sp<Looper>& looper) :
         mLooper(looper),
         mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), mVirtualKeyQuietTime(-1),
         mKeyRepeatTimeout(-1), mKeyRepeatDelay(-1),
         mMaxEventsPerSecond(-1) {
     JNIEnv* env = jniEnv();
 
+    mContextObj = env->NewGlobalRef(contextObj);
     mCallbacksObj = env->NewGlobalRef(callbacksObj);
 
     {
@@ -269,6 +280,7 @@
 NativeInputManager::~NativeInputManager() {
     JNIEnv* env = jniEnv();
 
+    env->DeleteGlobalRef(mContextObj);
     env->DeleteGlobalRef(mCallbacksObj);
 }
 
@@ -292,9 +304,13 @@
 
 void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
     if (displayId == 0) {
-        AutoMutex _l(mLock);
+        { // acquire lock
+            AutoMutex _l(mLock);
 
-        if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
+            if (mLocked.displayWidth == width && mLocked.displayHeight == height) {
+                return;
+            }
+
             mLocked.displayWidth = width;
             mLocked.displayHeight = height;
 
@@ -302,7 +318,7 @@
             if (controller != NULL) {
                 controller->setDisplaySize(width, height);
             }
-        }
+        } // release lock
     }
 }
 
@@ -432,40 +448,33 @@
     if (controller == NULL) {
         ensureSpriteControllerLocked();
 
-        controller = new PointerController(mLooper, mLocked.spriteController);
+        controller = new PointerController(this, mLooper, mLocked.spriteController);
         mLocked.pointerController = controller;
 
         controller->setDisplaySize(mLocked.displayWidth, mLocked.displayHeight);
         controller->setDisplayOrientation(mLocked.displayOrientation);
 
         JNIEnv* env = jniEnv();
-        jobject iconObj = env->CallObjectMethod(mCallbacksObj, gCallbacksClassInfo.getPointerIcon);
-        if (!checkAndClearExceptionFromCallback(env, "getPointerIcon") && iconObj) {
-            jfloat iconHotSpotX = env->GetFloatField(iconObj, gPointerIconClassInfo.hotSpotX);
-            jfloat iconHotSpotY = env->GetFloatField(iconObj, gPointerIconClassInfo.hotSpotY);
-            jobject iconBitmapObj = env->GetObjectField(iconObj, gPointerIconClassInfo.bitmap);
-            if (iconBitmapObj) {
-                SkBitmap* iconBitmap = GraphicsJNI::getNativeBitmap(env, iconBitmapObj);
-                if (iconBitmap) {
-                    controller->setPointerIcon(iconBitmap, iconHotSpotX, iconHotSpotY);
-                }
-                env->DeleteLocalRef(iconBitmapObj);
+        jobject pointerIconObj = env->CallObjectMethod(mCallbacksObj,
+                gCallbacksClassInfo.getPointerIcon);
+        if (!checkAndClearExceptionFromCallback(env, "getPointerIcon")) {
+            PointerIcon pointerIcon;
+            status_t status = android_view_PointerIcon_load(env, pointerIconObj,
+                    mContextObj, &pointerIcon);
+            if (!status && !pointerIcon.isNullIcon()) {
+                controller->setPointerIcon(SpriteIcon(pointerIcon.bitmap,
+                        pointerIcon.hotSpotX, pointerIcon.hotSpotY));
+            } else {
+                controller->setPointerIcon(SpriteIcon());
             }
-            env->DeleteLocalRef(iconObj);
+            env->DeleteLocalRef(pointerIconObj);
         }
 
-        updateInactivityFadeDelayLocked(controller);
+        updateInactivityTimeoutLocked(controller);
     }
     return controller;
 }
 
-sp<SpotControllerInterface> NativeInputManager::obtainSpotController(int32_t deviceId) {
-    AutoMutex _l(mLock);
-
-    ensureSpriteControllerLocked();
-    return new SpotController(mLooper, mLocked.spriteController);
-}
-
 void NativeInputManager::ensureSpriteControllerLocked() {
     if (mLocked.spriteController == NULL) {
         JNIEnv* env = jniEnv();
@@ -646,16 +655,16 @@
 
         sp<PointerController> controller = mLocked.pointerController.promote();
         if (controller != NULL) {
-            updateInactivityFadeDelayLocked(controller);
+            updateInactivityTimeoutLocked(controller);
         }
     }
 }
 
-void NativeInputManager::updateInactivityFadeDelayLocked(const sp<PointerController>& controller) {
+void NativeInputManager::updateInactivityTimeoutLocked(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);
+    controller->setInactivityTimeout(lightsOut
+            ? PointerController::INACTIVITY_TIMEOUT_SHORT
+            : PointerController::INACTIVITY_TIMEOUT_NORMAL);
 }
 
 bool NativeInputManager::isScreenOn() {
@@ -856,6 +865,17 @@
     return result;
 }
 
+void NativeInputManager::loadPointerResources(PointerResources* outResources) {
+    JNIEnv* env = jniEnv();
+
+    loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_HOVER,
+            &outResources->spotHover);
+    loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_TOUCH,
+            &outResources->spotTouch);
+    loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_ANCHOR,
+            &outResources->spotAnchor);
+}
+
 
 // ----------------------------------------------------------------------------
 
@@ -871,10 +891,10 @@
 }
 
 static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
-        jobject callbacks, jobject messageQueueObj) {
+        jobject contextObj, jobject callbacksObj, jobject messageQueueObj) {
     if (gNativeInputManager == NULL) {
         sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
-        gNativeInputManager = new NativeInputManager(callbacks, looper);
+        gNativeInputManager = new NativeInputManager(contextObj, callbacksObj, looper);
     } else {
         LOGE("Input manager already initialized.");
         jniThrowRuntimeException(env, "Input manager already initialized.");
@@ -1207,7 +1227,8 @@
 
 static JNINativeMethod gInputManagerMethods[] = {
     /* name, signature, funcPtr */
-    { "nativeInit", "(Lcom/android/server/wm/InputManager$Callbacks;Landroid/os/MessageQueue;)V",
+    { "nativeInit", "(Landroid/content/Context;"
+            "Lcom/android/server/wm/InputManager$Callbacks;Landroid/os/MessageQueue;)V",
             (void*) android_server_InputManager_nativeInit },
     { "nativeStart", "()V",
             (void*) android_server_InputManager_nativeStart },
@@ -1328,7 +1349,7 @@
             "getPointerLayer", "()I");
 
     GET_METHOD_ID(gCallbacksClassInfo.getPointerIcon, gCallbacksClassInfo.clazz,
-            "getPointerIcon", "()Lcom/android/server/wm/InputManager$PointerIcon;");
+            "getPointerIcon", "()Landroid/view/PointerIcon;");
 
     // KeyEvent
 
@@ -1373,19 +1394,6 @@
     GET_FIELD_ID(gConfigurationClassInfo.navigation, gConfigurationClassInfo.clazz,
             "navigation", "I");
 
-    // PointerIcon
-
-    FIND_CLASS(gPointerIconClassInfo.clazz, "com/android/server/wm/InputManager$PointerIcon");
-
-    GET_FIELD_ID(gPointerIconClassInfo.bitmap, gPointerIconClassInfo.clazz,
-            "bitmap", "Landroid/graphics/Bitmap;");
-
-    GET_FIELD_ID(gPointerIconClassInfo.hotSpotX, gPointerIconClassInfo.clazz,
-            "hotSpotX", "F");
-
-    GET_FIELD_ID(gPointerIconClassInfo.hotSpotY, gPointerIconClassInfo.clazz,
-            "hotSpotY", "F");
-
     return 0;
 }