MH2 | Add rough proxy callback postEvents method

Add post events method to HalProxyCallback without fully implementing
the wakeup events handling and pending blocking writes. Also change
mSensorList of the halProxy to mSensors which is a map from sensorHandle
to sensorInfo so that getNumWakeupEvents method of callback can find
sensorinfo info from sensorhandle of event type. Instantiate
halproxycallback vector in HalProxy for each subhal in the ctor as well.
Add very simple test for the postEvents method of callback.

Bug: 136511617
Test: New unit test passes.
Change-Id: I39c861cff286f24992bfcfcaa6bb468b4544b0e0
diff --git a/sensors/2.0/multihal/HalProxy.cpp b/sensors/2.0/multihal/HalProxy.cpp
index b4d2466..5a45a44 100644
--- a/sensors/2.0/multihal/HalProxy.cpp
+++ b/sensors/2.0/multihal/HalProxy.cpp
@@ -16,12 +16,15 @@
 
 #include "HalProxy.h"
 
+#include "SubHal.h"
+
 #include <android/hardware/sensors/2.0/types.h>
 
 #include <dlfcn.h>
 
 #include <fstream>
 #include <functional>
+#include <thread>
 
 namespace android {
 namespace hardware {
@@ -29,53 +32,22 @@
 namespace V2_0 {
 namespace implementation {
 
+using ::android::hardware::sensors::V2_0::EventQueueFlagBits;
+
 typedef ISensorsSubHal*(SensorsHalGetSubHalFunc)(uint32_t*);
 
-// TODO: Use this wake lock name as the prefix to all sensors HAL wake locks acquired.
-// constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP";
-
-// TODO: Use the following class as a starting point for implementing the full HalProxyCallback
-// along with being inspiration for how to implement the ScopedWakelock class.
-/**
- * Callback class used to provide the HalProxy with the index of which subHal is invoking
- */
-class SensorsCallbackProxy : public ISensorsCallback {
-  public:
-    SensorsCallbackProxy(wp<HalProxy>& halProxy, int32_t subHalIndex)
-        : mHalProxy(halProxy), mSubHalIndex(subHalIndex) {}
-
-    Return<void> onDynamicSensorsConnected(
-            const hidl_vec<SensorInfo>& dynamicSensorsAdded) override {
-        sp<HalProxy> halProxy(mHalProxy.promote());
-        if (halProxy != nullptr) {
-            return halProxy->onDynamicSensorsConnected(dynamicSensorsAdded, mSubHalIndex);
-        }
-        return Return<void>();
-    }
-
-    Return<void> onDynamicSensorsDisconnected(
-            const hidl_vec<int32_t>& dynamicSensorHandlesRemoved) override {
-        sp<HalProxy> halProxy(mHalProxy.promote());
-        if (halProxy != nullptr) {
-            return halProxy->onDynamicSensorsDisconnected(dynamicSensorHandlesRemoved,
-                                                          mSubHalIndex);
-        }
-        return Return<void>();
-    }
-
-  private:
-    wp<HalProxy>& mHalProxy;
-    int32_t mSubHalIndex;
-};
+ScopedWakelock::ScopedWakelock() {
+    // TODO: Implement
+}
 
 HalProxy::HalProxy() {
     const char* kMultiHalConfigFile = "/vendor/etc/sensors/hals.conf";
     initializeSubHalListFromConfigFile(kMultiHalConfigFile);
-    initializeSensorList();
+    initializeSubHalCallbacksAndSensorList();
 }
 
 HalProxy::HalProxy(std::vector<ISensorsSubHal*>& subHalList) : mSubHalList(subHalList) {
-    initializeSensorList();
+    initializeSubHalCallbacksAndSensorList();
 }
 
 HalProxy::~HalProxy() {
@@ -84,7 +56,11 @@
 }
 
 Return<void> HalProxy::getSensorsList(getSensorsList_cb _hidl_cb) {
-    _hidl_cb(mSensorList);
+    std::vector<SensorInfo> sensors;
+    for (const auto& iter : mSensors) {
+        sensors.push_back(iter.second);
+    }
+    _hidl_cb(sensors);
     return Void();
 }
 
@@ -148,6 +124,17 @@
 
     // TODO: start threads to read wake locks and process events from sub HALs.
 
+    for (size_t i = 0; i < mSubHalList.size(); i++) {
+        auto subHal = mSubHalList[i];
+        const auto& subHalCallback = mSubHalCallbacks[i];
+        Result currRes = subHal->initialize(subHalCallback);
+        if (currRes != Result::OK) {
+            result = currRes;
+            ALOGE("Subhal '%s' failed to initialize.", subHal->getName().c_str());
+            break;
+        }
+    }
+
     return result;
 }
 
@@ -239,6 +226,13 @@
     }
 }
 
+void HalProxy::initializeSubHalCallbacks() {
+    for (size_t subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) {
+        sp<IHalProxyCallback> callback = new HalProxyCallback(this, subHalIndex);
+        mSubHalCallbacks.push_back(callback);
+    }
+}
+
 void HalProxy::initializeSensorList() {
     for (size_t subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) {
         ISensorsSubHal* subHal = mSubHalList[subHalIndex];
@@ -250,7 +244,7 @@
                     ALOGV("Loaded sensor: %s", sensor.name.c_str());
                     sensor.sensorHandle |= (subHalIndex << 24);
                     setDirectChannelFlags(&sensor, subHal);
-                    mSensorList.push_back(sensor);
+                    mSensors[sensor.sensorHandle] = sensor;
                 }
             }
         });
@@ -260,6 +254,29 @@
     }
 }
 
+void HalProxy::initializeSubHalCallbacksAndSensorList() {
+    initializeSubHalCallbacks();
+    initializeSensorList();
+}
+
+void HalProxy::postEventsToMessageQueue(const std::vector<Event>& events) {
+    std::lock_guard<std::mutex> lock(mEventQueueMutex);
+    size_t numToWrite = std::min(events.size(), mEventQueue->availableToWrite());
+    if (numToWrite > 0) {
+        if (mEventQueue->write(events.data(), numToWrite)) {
+            // TODO: While loop if mEventQueue->avaiableToWrite > 0 to possibly fit in more writes
+            // immediately
+            mEventQueueFlag->wake(static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS));
+        } else {
+            numToWrite = 0;
+        }
+    }
+    if (numToWrite < events.size()) {
+        // TODO: Post from events[numToWrite -> end] to background events queue
+        // Signal background thread
+    }
+}
+
 void HalProxy::setDirectChannelFlags(SensorInfo* sensorInfo, ISensorsSubHal* subHal) {
     bool sensorSupportsDirectChannel =
             (sensorInfo->flags & (V1_0::SensorFlagBits::MASK_DIRECT_REPORT |
@@ -282,6 +299,50 @@
     return sensorHandle & (~kSensorHandleSubHalIndexMask);
 }
 
+void HalProxyCallback::postEvents(const std::vector<Event>& events, ScopedWakelock wakelock) {
+    (void)wakelock;
+    size_t numWakeupEvents;
+    std::vector<Event> processedEvents = processEvents(events, &numWakeupEvents);
+    if (numWakeupEvents > 0) {
+        ALOG_ASSERT(wakelock.isLocked(),
+                    "Wakeup events posted while wakelock unlocked for subhal"
+                    " w/ index %zu.",
+                    mSubHalIndex);
+    } else {
+        ALOG_ASSERT(!wakelock.isLocked(),
+                    "No Wakeup events posted but wakelock locked for subhal"
+                    " w/ index %zu.",
+                    mSubHalIndex);
+    }
+
+    mHalProxy->postEventsToMessageQueue(processedEvents);
+}
+
+ScopedWakelock HalProxyCallback::createScopedWakelock(bool lock) {
+    ScopedWakelock wakelock;
+    wakelock.mLocked = lock;
+    return wakelock;
+}
+
+std::vector<Event> HalProxyCallback::processEvents(const std::vector<Event>& events,
+                                                   size_t* numWakeupEvents) const {
+    std::vector<Event> eventsOut;
+    *numWakeupEvents = 0;
+    for (Event event : events) {
+        event.sensorHandle = setSubHalIndex(event.sensorHandle);
+        eventsOut.push_back(event);
+        if ((mHalProxy->getSensorInfo(event.sensorHandle).flags & V1_0::SensorFlagBits::WAKE_UP) !=
+            0) {
+            (*numWakeupEvents)++;
+        }
+    }
+    return eventsOut;
+}
+
+uint32_t HalProxyCallback::setSubHalIndex(uint32_t sensorHandle) const {
+    return sensorHandle | mSubHalIndex << 24;
+}
+
 }  // namespace implementation
 }  // namespace V2_0
 }  // namespace sensors