Use strong pointer in ALooper to avoid use-after-free

If the endpoint that has a reference to the ASensorEventQueue goes away
without calling ASensorManager_destroyEventQueue, then the event queue's
reference goes to 0. This causes the event queue to be destroyed, but
the looper may still call it since it hasn't been invalidated yet
causing a use-after-free.

To avoid this, store the event queue as a weak pointer in the looper's
queue and attempt to promote it to a strong pointer when it needs to be
used. If it can't be promoted, then it is ignored and cleared later.

Bug: 175074139
Test: Load Android firmware image and run the camera app to verify no
crashes are seen.

Merged-In: I1439bf9c0a725818889f7be64e234d952363f4db
Change-Id: I1439bf9c0a725818889f7be64e234d952363f4db
(cherry picked from commit 7d712cfe6ddf86c07c4f2baee74ec948c7fc72d0)
diff --git a/sensorservice/libsensorndkbridge/ALooper.cpp b/sensorservice/libsensorndkbridge/ALooper.cpp
index 9930ad4..d3ddbff 100644
--- a/sensorservice/libsensorndkbridge/ALooper.cpp
+++ b/sensorservice/libsensorndkbridge/ALooper.cpp
@@ -23,12 +23,14 @@
 #include <android-base/logging.h>
 
 using android::Mutex;
+using android::sp;
+using android::wp;
 
 ALooper::ALooper()
     : mAwoken(false) {
 }
 
-void ALooper::signalSensorEvents(ASensorEventQueue *queue) {
+void ALooper::signalSensorEvents(wp<ASensorEventQueue> queue) {
     Mutex::Autolock autoLock(mLock);
     mReadyQueues.insert(queue);
     mCondition.signal();
@@ -71,8 +73,11 @@
     if (!mReadyQueues.empty()) {
         result = ALOOPER_POLL_CALLBACK;
 
-        for (auto queue : mReadyQueues) {
-            queue->dispatchCallback();
+        for (auto& queue : mReadyQueues) {
+            sp<ASensorEventQueue> promotedQueue = queue.promote();
+            if (promotedQueue != nullptr) {
+                promotedQueue->dispatchCallback();
+            }
         }
 
         mReadyQueues.clear();
@@ -86,8 +91,7 @@
     return result;
 }
 
-void ALooper::invalidateSensorQueue(ASensorEventQueue *queue) {
+void ALooper::invalidateSensorQueue(wp<ASensorEventQueue> queue) {
     Mutex::Autolock autoLock(mLock);
     mReadyQueues.erase(queue);
 }
-
diff --git a/sensorservice/libsensorndkbridge/ALooper.h b/sensorservice/libsensorndkbridge/ALooper.h
index 601eca9..aa14e03 100644
--- a/sensorservice/libsensorndkbridge/ALooper.h
+++ b/sensorservice/libsensorndkbridge/ALooper.h
@@ -21,6 +21,7 @@
 #include <android-base/macros.h>
 #include <utils/Condition.h>
 #include <utils/Mutex.h>
+#include <utils/RefBase.h>
 
 #include <set>
 
@@ -29,18 +30,18 @@
 struct ALooper {
     ALooper();
 
-    void signalSensorEvents(ASensorEventQueue *queue);
+    void signalSensorEvents(android::wp<ASensorEventQueue> queue);
     void wake();
 
     int pollOnce(int timeoutMillis, int *outFd, int *outEvents, void **outData);
 
-    void invalidateSensorQueue(ASensorEventQueue *queue);
+    void invalidateSensorQueue(android::wp<ASensorEventQueue> queue);
 
 private:
     android::Mutex mLock;
     android::Condition mCondition;
 
-    std::set<ASensorEventQueue *> mReadyQueues;
+    std::set<android::wp<ASensorEventQueue>> mReadyQueues;
     bool mAwoken;
 
     DISALLOW_COPY_AND_ASSIGN(ALooper);