Hold a weak reference to PointerController when handling vsync

Currently PointerController starts listening to display events
immediately (in its constructor) and never explicitly removes
the callback. The reference dangling from the looper
prevents the PointerController instance from being deleted
when all the clients have released their references.

As a result, when USB or BT mouse is disconnected,
the mouse stays frozen on screen and only goes away
after a 15 sec inactivity timeout.

This change introduces an intermediary LooperCallback
which holds only a weak reference to PointerController.
The pointer now disappears immediately upon mouse
disconnect.

Bug: 30824220
Change-Id: I5f7208dbfa381b3e21f248cc0da402f307faa184
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 27193b7..abef66f 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -36,6 +36,29 @@
 
 namespace android {
 
+// --- WeakLooperCallback ---
+
+class WeakLooperCallback: public LooperCallback {
+protected:
+    virtual ~WeakLooperCallback() { }
+
+public:
+    WeakLooperCallback(const wp<LooperCallback>& callback) :
+        mCallback(callback) {
+    }
+
+    virtual int handleEvent(int fd, int events, void* data) {
+        sp<LooperCallback> callback = mCallback.promote();
+        if (callback != NULL) {
+            return callback->handleEvent(fd, events, data);
+        }
+        return 0; // the client is gone, remove the callback
+    }
+
+private:
+    wp<LooperCallback> mCallback;
+};
+
 // --- PointerController ---
 
 // Time to wait before starting the fade when the pointer is inactive.
@@ -57,10 +80,11 @@
         const sp<Looper>& looper, const sp<SpriteController>& spriteController) :
         mPolicy(policy), mLooper(looper), mSpriteController(spriteController) {
     mHandler = new WeakMessageHandler(this);
+    mCallback = new WeakLooperCallback(this);
 
     if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
         mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
-                       Looper::EVENT_INPUT, this, nullptr);
+                       Looper::EVENT_INPUT, mCallback, nullptr);
     } else {
         ALOGE("Failed to initialize DisplayEventReceiver.");
     }