Merge "Wifi: Move LOCAL_VINTF_FRAGMENTS to executables"
diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp
index 697bf9e..216cc20 100644
--- a/sensors/2.0/multihal/Android.bp
+++ b/sensors/2.0/multihal/Android.bp
@@ -42,6 +42,7 @@
     srcs: [
         "service.cpp",
         "HalProxy.cpp",
+        "ScopedWakelock.cpp",
     ],
     init_rc: ["android.hardware.sensors@2.0-service-multihal.rc"],
     vintf_fragments: ["android.hardware.sensors@2.0-multihal.xml"],
@@ -61,6 +62,7 @@
     vendor_available: true,
     srcs: [
         "HalProxy.cpp",
+        "ScopedWakelock.cpp",
     ],
     export_header_lib_headers: [
         "android.hardware.sensors@2.0-multihal.header",
diff --git a/sensors/2.0/multihal/HalProxy.cpp b/sensors/2.0/multihal/HalProxy.cpp
index b4d2466..81d1b64 100644
--- a/sensors/2.0/multihal/HalProxy.cpp
+++ b/sensors/2.0/multihal/HalProxy.cpp
@@ -16,12 +16,17 @@
 
 #include "HalProxy.h"
 
+#include "SubHal.h"
+
 #include <android/hardware/sensors/2.0/types.h>
 
+#include "hardware_legacy/power.h"
+
 #include <dlfcn.h>
 
 #include <fstream>
 #include <functional>
+#include <thread>
 
 namespace android {
 namespace hardware {
@@ -29,53 +34,18 @@
 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;
-};
-
 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 +54,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 +122,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 +224,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 +242,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 +252,48 @@
     }
 }
 
+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
+    }
+}
+
+// TODO: Implement the wakelock timeout in these next two methods. Also pass in the subhal
+// index for better tracking.
+
+void HalProxy::incrementRefCountAndMaybeAcquireWakelock() {
+    std::lock_guard<std::mutex> lockGuard(mWakelockRefCountMutex);
+    if (mWakelockRefCount == 0) {
+        acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName);
+    }
+    mWakelockRefCount++;
+}
+
+void HalProxy::decrementRefCountAndMaybeReleaseWakelock() {
+    std::lock_guard<std::mutex> lockGuard(mWakelockRefCountMutex);
+    mWakelockRefCount--;
+    if (mWakelockRefCount == 0) {
+        release_wake_lock(kWakeLockName);
+    }
+}
+
 void HalProxy::setDirectChannelFlags(SensorInfo* sensorInfo, ISensorsSubHal* subHal) {
     bool sensorSupportsDirectChannel =
             (sensorInfo->flags & (V1_0::SensorFlagBits::MASK_DIRECT_REPORT |
@@ -282,6 +316,49 @@
     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(mHalProxy, 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
diff --git a/sensors/2.0/multihal/ScopedWakelock.cpp b/sensors/2.0/multihal/ScopedWakelock.cpp
new file mode 100644
index 0000000..0430fa3
--- /dev/null
+++ b/sensors/2.0/multihal/ScopedWakelock.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ScopedWakelock.h"
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V2_0 {
+namespace implementation {
+
+ScopedWakelock::ScopedWakelock(IScopedWakelockRefCounter* refCounter, bool locked)
+    : mRefCounter(refCounter), mLocked(locked) {
+    // TODO: Move this implementation into HalProxy object instead
+    if (mLocked) {
+        mRefCounter->incrementRefCountAndMaybeAcquireWakelock();
+    }
+}
+
+ScopedWakelock::~ScopedWakelock() {
+    // TODO: Move this implementation into HalProxy object instead
+    if (mLocked) {
+        mRefCounter->decrementRefCountAndMaybeReleaseWakelock();
+    }
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace sensors
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/sensors/2.0/multihal/include/HalProxy.h b/sensors/2.0/multihal/include/HalProxy.h
index 4ecb58b..bdcc1ff 100644
--- a/sensors/2.0/multihal/include/HalProxy.h
+++ b/sensors/2.0/multihal/include/HalProxy.h
@@ -24,6 +24,8 @@
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 
+#include <map>
+
 namespace android {
 namespace hardware {
 namespace sensors {
@@ -39,13 +41,15 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 
-class HalProxy : public ISensors {
+class HalProxy : public ISensors, public IScopedWakelockRefCounter {
   public:
     using Event = ::android::hardware::sensors::V1_0::Event;
     using OperationMode = ::android::hardware::sensors::V1_0::OperationMode;
     using RateLevel = ::android::hardware::sensors::V1_0::RateLevel;
     using Result = ::android::hardware::sensors::V1_0::Result;
+    using SensorInfo = ::android::hardware::sensors::V1_0::SensorInfo;
     using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
+    using ISensorsSubHal = ::android::hardware::sensors::V2_0::implementation::ISensorsSubHal;
 
     explicit HalProxy();
     // Test only constructor.
@@ -91,10 +95,45 @@
     Return<void> onDynamicSensorsDisconnected(const hidl_vec<int32_t>& dynamicSensorHandlesRemoved,
                                               int32_t subHalIndex);
 
+    // Below methods follow IScopedWakelockRefCounter
+
+    /**
+     * Increment ref count and maybe acquire wakelock.
+     */
+    void incrementRefCountAndMaybeAcquireWakelock() override;
+
+    /**
+     * Decrement ref count and maybe release wakelock.
+     */
+    void decrementRefCountAndMaybeReleaseWakelock() override;
+
+    // Below methods are for HalProxyCallback
+
+    /**
+     * Post events to the event message queue if there is room to write them. Otherwise post the
+     * remaining events to a background thread for a blocking write with a 5 second timeout.
+     *
+     * @param events The list of events to post to the message queue.
+     */
+    void postEventsToMessageQueue(const std::vector<Event>& events);
+
+    /**
+     * Get the SensorInfo object associated with the sensorHandle.
+     *
+     * @param sensorHandle The sensorHandle for the sensor.
+     *
+     * @return The sensor info for the sensor.
+     */
+    const SensorInfo& getSensorInfo(uint32_t sensorHandle) const {
+        return mSensors.at(sensorHandle);
+    }
+
   private:
     using EventMessageQueue = MessageQueue<Event, kSynchronizedReadWrite>;
     using WakeLockMessageQueue = MessageQueue<uint32_t, kSynchronizedReadWrite>;
 
+    const char* kWakeLockName = "SensorsHAL_WAKEUP";
+
     /**
      * The Event FMQ where sensor events are written
      */
@@ -120,14 +159,16 @@
      */
     std::vector<ISensorsSubHal*> mSubHalList;
 
+    std::vector<const sp<IHalProxyCallback>> mSubHalCallbacks;
+
     /**
-     * List of SensorInfo objects that contains the sensor info from subhals as
+     * Map of sensor handles to SensorInfo objects that contains the sensor info from subhals as
      * well as the modified sensor handle for the framework.
      *
-     * The subhal index is encoded in the first byte of the sensor handle and
-     * the remaining bytes are generated by the subhal to identify the sensor.
+     * The subhal index is encoded in the first byte of the sensor handle and the remaining
+     * bytes are generated by the subhal to identify the sensor.
      */
-    std::vector<SensorInfo> mSensorList;
+    std::map<uint32_t, SensorInfo> mSensors;
 
     //! The current operation mode for all subhals.
     OperationMode mCurrentOperationMode = OperationMode::NORMAL;
@@ -135,6 +176,15 @@
     //! The single subHal that supports directChannel reporting.
     ISensorsSubHal* mDirectChannelSubHal = nullptr;
 
+    //! The mutex for the event queue.
+    std::mutex mEventQueueMutex;
+
+    //! The scoped wakelock ref count.
+    size_t mWakelockRefCount = 0;
+
+    //! The mutex guarding the mWakelockRefCount variable
+    std::mutex mWakelockRefCountMutex;
+
     //! The bit mask used to get the subhal index from a sensor handle.
     static constexpr uint32_t kSensorHandleSubHalIndexMask = 0xFF000000;
 
@@ -145,12 +195,22 @@
     void initializeSubHalListFromConfigFile(const char* configFileName);
 
     /**
+     * Initialize the HalProxyCallback vector using the list of subhals.
+     */
+    void initializeSubHalCallbacks();
+
+    /**
      * Initialize the list of SensorInfo objects in mSensorList by getting sensors from each
      * subhal.
      */
     void initializeSensorList();
 
     /**
+     * Calls the above two helper methods which are shared in both ctors.
+     */
+    void initializeSubHalCallbacksAndSensorList();
+
+    /**
      * Clear direct channel flags if the HalProxy has already chosen a subhal as its direct channel
      * subhal. Set the directChannelSubHal pointer to the subHal passed in if this is the first
      * direct channel enabled sensor seen.
@@ -179,6 +239,40 @@
     static uint32_t clearSubHalIndex(uint32_t sensorHandle);
 };
 
+/**
+ * Callback class used to provide the HalProxy with the index of which subHal is invoking
+ */
+class HalProxyCallback : public IHalProxyCallback {
+    using SensorInfo = ::android::hardware::sensors::V1_0::SensorInfo;
+
+  public:
+    HalProxyCallback(HalProxy* halProxy, int32_t subHalIndex)
+        : mHalProxy(halProxy), mSubHalIndex(subHalIndex) {}
+
+    Return<void> onDynamicSensorsConnected(
+            const hidl_vec<SensorInfo>& dynamicSensorsAdded) override {
+        return mHalProxy->onDynamicSensorsConnected(dynamicSensorsAdded, mSubHalIndex);
+    }
+
+    Return<void> onDynamicSensorsDisconnected(
+            const hidl_vec<int32_t>& dynamicSensorHandlesRemoved) override {
+        return mHalProxy->onDynamicSensorsDisconnected(dynamicSensorHandlesRemoved, mSubHalIndex);
+    }
+
+    void postEvents(const std::vector<Event>& events, ScopedWakelock wakelock);
+
+    ScopedWakelock createScopedWakelock(bool lock);
+
+  private:
+    HalProxy* mHalProxy;
+    int32_t mSubHalIndex;
+
+    std::vector<Event> processEvents(const std::vector<Event>& events,
+                                     size_t* numWakeupEvents) const;
+
+    uint32_t setSubHalIndex(uint32_t sensorHandle) const;
+};
+
 }  // namespace implementation
 }  // namespace V2_0
 }  // namespace sensors
diff --git a/sensors/2.0/multihal/include/ScopedWakelock.h b/sensors/2.0/multihal/include/ScopedWakelock.h
new file mode 100644
index 0000000..a151f15
--- /dev/null
+++ b/sensors/2.0/multihal/include/ScopedWakelock.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V2_0 {
+namespace implementation {
+
+class IScopedWakelockRefCounter {
+  public:
+    virtual void incrementRefCountAndMaybeAcquireWakelock() = 0;
+    virtual void decrementRefCountAndMaybeReleaseWakelock() = 0;
+    // Virtual dtor needed for compilation success
+    virtual ~IScopedWakelockRefCounter(){};
+};
+
+/**
+ * Wrapper around wake lock acquisition functions (acquire/release_wake_lock) that provides a
+ * RAII-style mechanism for keeping a wake lock held for the duration of a scoped block.
+ * When a ScopedWakelock is created, it increments the reference count stored in the HalProxy
+ * for the sub-HALs specific wake lock, acquiring the wake lock if necessary. When the object goes
+ * out of scope, the ref count is decremented, potentially releasing the wake lock if no other
+ * references to the wake lock exist.
+ *
+ * This class is allocated through the createScopedWakelock callback inside the IHalProxyCallback
+ * provided to sub-HALs during initialization and should be used for all wake lock acquisition
+ * inside of the sub-HAL to ensure wake locks are not held indefinitely.
+ *
+ * The most prevalent use case for this class will be for posting events to the framework through
+ * the postEvents HalProxy callback. The expectation is that sub-HALs will create this
+ * ScopedWakelock through the createScopedWakelock upon receiving a sensor events. The lock boolean
+ * provided to createScopedWakelock will be set the according to whether the sensor events are
+ * from wakeup sensors. Then, the sub-HAL will perform any processing necessary before invoking the
+ * postEvents callback passing in the previously created ScopedWakelock. At this point, ownership
+ * of the object will be passed to the HalProxy that will then be responsible for ensuring any
+ * wake locks continue to be held, if necessary.
+ */
+class ScopedWakelock {
+  public:
+    ScopedWakelock(ScopedWakelock&&) = default;
+    ScopedWakelock& operator=(ScopedWakelock&&) = default;
+    virtual ~ScopedWakelock();
+
+    bool isLocked() const { return mLocked; }
+
+  private:
+    friend class HalProxyCallback;
+    IScopedWakelockRefCounter* mRefCounter;
+    bool mLocked;
+    ScopedWakelock(IScopedWakelockRefCounter* refCounter, bool locked);
+    ScopedWakelock(const ScopedWakelock&) = delete;
+    ScopedWakelock& operator=(const ScopedWakelock&) = delete;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace sensors
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/sensors/2.0/multihal/include/SubHal.h b/sensors/2.0/multihal/include/SubHal.h
index e84cba5..e7eedaa 100644
--- a/sensors/2.0/multihal/include/SubHal.h
+++ b/sensors/2.0/multihal/include/SubHal.h
@@ -16,15 +16,13 @@
 
 #pragma once
 
+#include "ScopedWakelock.h"
+
 #include <android/hardware/sensors/1.0/types.h>
 #include <android/hardware/sensors/2.0/ISensors.h>
 
 #include <vector>
 
-using ::android::hardware::sensors::V1_0::Event;
-using ::android::hardware::sensors::V1_0::Result;
-using ::android::hardware::sensors::V1_0::SensorInfo;
-
 // Indicates the current version of the multiHAL interface formatted as (HAL major version) << 24 |
 // (HAL minor version) << 16 | (multiHAL version)
 #define SUB_HAL_2_0_VERSION 0x02000000
@@ -35,44 +33,9 @@
 namespace V2_0 {
 namespace implementation {
 
-/**
- * Wrapper around wake lock acquisition functions (acquire/release_wake_lock) that provides a
- * RAII-style mechanism for keeping a wake lock held for the duration of a scoped block.
- * When a ScopedWakelock is created, it increments the reference count stored in the HalProxy
- * for the sub-HALs specific wake lock, acquiring the wake lock if necessary. When the object goes
- * out of scope, the ref count is decremented, potentially releasing the wake lock if no other
- * references to the wake lock exist.
- *
- * This class is allocated through the createScopedWakelock callback inside the IHalProxyCallback
- * provided to sub-HALs during initialization and should be used for all wake lock acquisition
- * inside of the sub-HAL to ensure wake locks are not held indefinitely.
- *
- * The most prevalent use case for this class will be for posting events to the framework through
- * the postEvents HalProxy callback. The expectation is that sub-HALs will create this
- * ScopedWakelock through the createScopedWakelock upon receiving a sensor events. The lock boolean
- * provided to createScopedWakelock will be set the according to whether the sensor events are
- * from wakeup sensors. Then, the sub-HAL will perform any processing necessary before invoking the
- * postEvents callback passing in the previously created ScopedWakelock. At this point, ownership
- * of the object will be passed to the HalProxy that will then be responsible for ensuring any
- * wake locks continue to be held, if necessary.
- */
-class ScopedWakelock {
-  public:
-    ScopedWakelock(ScopedWakelock&&) = default;
-    ScopedWakelock& operator=(ScopedWakelock&&) = default;
-    virtual ~ScopedWakelock() { mLocked = false; };
-
-    bool isLocked() const { return mLocked; }
-
-  protected:
-    bool mLocked;
-
-  private:
-    // TODO: Mark HalProxy's subclass of ScopedWakelock as a friend so that it can be initialized.
-    ScopedWakelock();
-    ScopedWakelock(const ScopedWakelock&) = delete;
-    ScopedWakelock& operator=(const ScopedWakelock&) = delete;
-};
+using ::android::hardware::sensors::V1_0::Event;
+using ::android::hardware::sensors::V1_0::Result;
+using ::android::hardware::sensors::V1_0::SensorInfo;
 
 /**
  * Interface that contains several callbacks into the HalProxy class to communicate dynamic sensor
@@ -169,7 +132,9 @@
     /**
      * First method invoked on the sub-HAL after it's allocated through sensorsHalGetSubHal() by the
      * HalProxy. Sub-HALs should use this to initialize any state and retain the callback given in
-     * order to communicate with the HalProxy.
+     * order to communicate with the HalProxy. Method will be called anytime the sensors framework
+     * restarts. Therefore, this method will be responsible for reseting the state of the subhal and
+     * cleaning up and reallocating any previously allocated data.
      *
      * @param halProxyCallback callback used to inform the HalProxy when a dynamic sensor's state
      *     changes, new sensor events should be sent to the framework, and when a new ScopedWakelock
diff --git a/sensors/2.0/multihal/tests/Android.bp b/sensors/2.0/multihal/tests/Android.bp
index 21ceb0c..ab260a4 100644
--- a/sensors/2.0/multihal/tests/Android.bp
+++ b/sensors/2.0/multihal/tests/Android.bp
@@ -33,6 +33,9 @@
         "libpower",
         "libutils",
     ],
+    static_libs: [
+        "android.hardware.sensors@2.0-HalProxy",
+    ],
 }
 
 cc_library {
diff --git a/sensors/2.0/multihal/tests/HalProxy_test.cpp b/sensors/2.0/multihal/tests/HalProxy_test.cpp
index 1e1f9e9..4b1a15e 100644
--- a/sensors/2.0/multihal/tests/HalProxy_test.cpp
+++ b/sensors/2.0/multihal/tests/HalProxy_test.cpp
@@ -16,18 +16,29 @@
 #include <gtest/gtest.h>
 
 #include <android/hardware/sensors/2.0/types.h>
+#include <fmq/MessageQueue.h>
 
 #include "HalProxy.h"
+#include "ScopedWakelock.h"
 #include "SensorsSubHal.h"
 
 #include <vector>
 
+#undef LOG_TAG
+#define LOG_TAG "HalProxy_test"
+
 namespace {
 
+using ::android::hardware::hidl_vec;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::Return;
+using ::android::hardware::sensors::V1_0::EventPayload;
 using ::android::hardware::sensors::V1_0::SensorFlagBits;
 using ::android::hardware::sensors::V1_0::SensorInfo;
 using ::android::hardware::sensors::V1_0::SensorType;
+using ::android::hardware::sensors::V2_0::ISensorsCallback;
 using ::android::hardware::sensors::V2_0::implementation::HalProxy;
+using ::android::hardware::sensors::V2_0::implementation::HalProxyCallback;
 using ::android::hardware::sensors::V2_0::subhal::implementation::AllSensorsSubHal;
 using ::android::hardware::sensors::V2_0::subhal::implementation::
         AllSupportDirectChannelSensorsSubHal;
@@ -36,10 +47,28 @@
         DoesNotSupportDirectChannelSensorsSubHal;
 using ::android::hardware::sensors::V2_0::subhal::implementation::OnChangeSensorsSubHal;
 using ::android::hardware::sensors::V2_0::subhal::implementation::SensorsSubHal;
-
 using ::android::hardware::sensors::V2_0::subhal::implementation::
         SetOperationModeFailingSensorsSubHal;
 
+using EventMessageQueue = MessageQueue<Event, ::android::hardware::kSynchronizedReadWrite>;
+using WakeupMessageQueue = MessageQueue<uint32_t, ::android::hardware::kSynchronizedReadWrite>;
+
+// The barebones sensors callback class passed into halproxy initialize calls
+class SensorsCallback : public ISensorsCallback {
+  public:
+    Return<void> onDynamicSensorsConnected(
+            const hidl_vec<SensorInfo>& /*dynamicSensorsAdded*/) override {
+        // Nothing yet
+        return Return<void>();
+    }
+
+    Return<void> onDynamicSensorsDisconnected(
+            const hidl_vec<int32_t>& /*dynamicSensorHandlesRemoved*/) override {
+        // Nothing yet
+        return Return<void>();
+    }
+};
+
 // Helper declarations follow
 
 /**
@@ -65,6 +94,22 @@
 void testSensorsListForOneDirectChannelEnabledSubHal(const std::vector<SensorInfo>& sensorsList,
                                                      size_t enabledSubHalIndex);
 
+/**
+ * Construct and return a HIDL Event type thats sensorHandle refers to a proximity sensor
+ *    which is a wakeup type sensor.
+ *
+ * @ return A proximity event.
+ */
+Event makeProximityEvent();
+
+/**
+ * Construct and return a HIDL Event type thats sensorHandle refers to a proximity sensor
+ *    which is a wakeup type sensor.
+ *
+ * @ return A proximity event.
+ */
+Event makeAccelerometerEvent();
+
 // Tests follow
 TEST(HalProxyTest, GetSensorsListOneSubHalTest) {
     AllSensorsSubHal subHal;
@@ -156,6 +201,86 @@
     });
 }
 
+TEST(HalProxyTest, PostSingleNonWakeupEvent) {
+    constexpr size_t kQueueSize = 5;
+    AllSensorsSubHal subHal;
+    std::vector<ISensorsSubHal*> subHals{&subHal};
+    HalProxy proxy(subHals);
+    std::unique_ptr<EventMessageQueue> eventQueue =
+            std::make_unique<EventMessageQueue>(kQueueSize, true);
+    std::unique_ptr<WakeupMessageQueue> wakeLockQueue =
+            std::make_unique<WakeupMessageQueue>(kQueueSize, true);
+    ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+    proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
+
+    std::vector<Event> events{makeAccelerometerEvent()};
+    subHal.postEvents(events, false /* wakeup */);
+
+    EXPECT_EQ(eventQueue->availableToRead(), 1);
+}
+
+TEST(HalProxyTest, PostMultipleNonWakeupEvent) {
+    constexpr size_t kQueueSize = 5;
+    constexpr size_t kNumEvents = 3;
+    AllSensorsSubHal subHal;
+    std::vector<ISensorsSubHal*> subHals{&subHal};
+    HalProxy proxy(subHals);
+    std::unique_ptr<EventMessageQueue> eventQueue =
+            std::make_unique<EventMessageQueue>(kQueueSize, true);
+    std::unique_ptr<WakeupMessageQueue> wakeLockQueue =
+            std::make_unique<WakeupMessageQueue>(kQueueSize, true);
+    ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+    proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
+
+    std::vector<Event> events;
+    for (size_t i = 0; i < kNumEvents; i++) {
+        events.push_back(makeAccelerometerEvent());
+    }
+    subHal.postEvents(events, false /* wakeup */);
+
+    EXPECT_EQ(eventQueue->availableToRead(), kNumEvents);
+}
+
+TEST(HalProxyTest, PostSingleWakeupEvent) {
+    constexpr size_t kQueueSize = 5;
+    AllSensorsSubHal subHal;
+    std::vector<ISensorsSubHal*> subHals{&subHal};
+    HalProxy proxy(subHals);
+    std::unique_ptr<EventMessageQueue> eventQueue =
+            std::make_unique<EventMessageQueue>(kQueueSize, true);
+    std::unique_ptr<WakeupMessageQueue> wakeLockQueue =
+            std::make_unique<WakeupMessageQueue>(kQueueSize, true);
+    ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+    proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
+
+    std::vector<Event> events{makeProximityEvent()};
+    subHal.postEvents(events, true /* wakeup */);
+
+    EXPECT_EQ(eventQueue->availableToRead(), 1);
+}
+
+TEST(HalProxyTest, PostMultipleWakeupEvents) {
+    constexpr size_t kQueueSize = 5;
+    constexpr size_t kNumEvents = 3;
+    AllSensorsSubHal subHal;
+    std::vector<ISensorsSubHal*> subHals{&subHal};
+    HalProxy proxy(subHals);
+    std::unique_ptr<EventMessageQueue> eventQueue =
+            std::make_unique<EventMessageQueue>(kQueueSize, true);
+    std::unique_ptr<WakeupMessageQueue> wakeLockQueue =
+            std::make_unique<WakeupMessageQueue>(kQueueSize, true);
+    ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+    proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
+
+    std::vector<Event> events;
+    for (size_t i = 0; i < kNumEvents; i++) {
+        events.push_back(makeProximityEvent());
+    }
+    subHal.postEvents(events, true /* wakeup */);
+
+    EXPECT_EQ(eventQueue->availableToRead(), kNumEvents);
+}
+
 // Helper implementations follow
 void testSensorsListFromProxyAndSubHal(const std::vector<SensorInfo>& proxySensorsList,
                                        const std::vector<SensorInfo>& subHalSensorsList) {
@@ -187,4 +312,24 @@
     }
 }
 
+Event makeProximityEvent() {
+    Event event;
+    event.timestamp = 0xFF00FF00;
+    // This is the sensorhandle of proximity, which is wakeup type
+    event.sensorHandle = 0x00000008;
+    event.sensorType = SensorType::PROXIMITY;
+    event.u = EventPayload();
+    return event;
+}
+
+Event makeAccelerometerEvent() {
+    Event event;
+    event.timestamp = 0xFF00FF00;
+    // This is the sensorhandle of proximity, which is wakeup type
+    event.sensorHandle = 0x00000001;
+    event.sensorType = SensorType::ACCELEROMETER;
+    event.u = EventPayload();
+    return event;
+}
+
 }  // namespace