Implement android.frameworks.sensorservice@1.0::IEventQueue.

Test: pass
Bug: 35219747
Change-Id: I52ddd64db500c23db22768fc0603bce0cc14f8c6
diff --git a/libs/sensor/include/sensor/SensorEventQueue.h b/libs/sensor/include/sensor/SensorEventQueue.h
index a03c7ee..baed2ee 100644
--- a/libs/sensor/include/sensor/SensorEventQueue.h
+++ b/libs/sensor/include/sensor/SensorEventQueue.h
@@ -83,7 +83,7 @@
     status_t disableSensor(Sensor const* sensor) const;
     status_t setEventRate(Sensor const* sensor, nsecs_t ns) const;
 
-    // these are here only to support SensorManager.java
+    // these are here only to support SensorManager.java and HIDL Frameworks SensorManager.
     status_t enableSensor(int32_t handle, int32_t samplingPeriodUs, int64_t maxBatchReportLatencyUs,
                           int reservedFlags) const;
     status_t disableSensor(int32_t handle) const;
diff --git a/services/sensorservice/hidl/Android.bp b/services/sensorservice/hidl/Android.bp
index f00c297..748dafc 100644
--- a/services/sensorservice/hidl/Android.bp
+++ b/services/sensorservice/hidl/Android.bp
@@ -1,6 +1,7 @@
 cc_library_shared {
     name: "libsensorservicehidl",
     srcs: [
+        "EventQueue.cpp",
         "DirectReportChannel.cpp",
         "SensorManager.cpp",
         "utils.cpp",
@@ -19,6 +20,9 @@
         "android.hardware.sensors@1.0",
         "android.hidl.base@1.0",
     ],
+    static_libs: [
+        "android.hardware.sensors@1.0-convert",
+    ],
     export_include_dirs: [
         "include/"
     ],
diff --git a/services/sensorservice/hidl/EventQueue.cpp b/services/sensorservice/hidl/EventQueue.cpp
new file mode 100644
index 0000000..86d365c
--- /dev/null
+++ b/services/sensorservice/hidl/EventQueue.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 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 "EventQueue.h"
+#include "utils.h"
+
+#include <utils/Looper.h>
+
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+class EventQueueLooperCallback : public ::android::LooperCallback {
+public:
+    EventQueueLooperCallback(sp<EventQueue> queue, sp<IEventQueueCallback> callback)
+            : mQueue(queue), mCallback(callback) {
+    }
+
+    int handleEvent(__unused int fd, __unused int events, __unused void* data) {
+
+        ASensorEvent event;
+        ssize_t actual;
+        const sp<::android::SensorEventQueue>& internalQueue = mQueue->mInternalQueue;
+
+        while ((actual = internalQueue->read(&event, 1 /* count */)) > 0) {
+            internalQueue->sendAck(&event, actual);
+            mCallback->onEvent(convertEvent(event));
+        }
+
+        return 1; // continue to receive callbacks
+    }
+
+private:
+    sp<EventQueue> mQueue;
+    sp<IEventQueueCallback> mCallback;
+};
+
+EventQueue::EventQueue(
+        sp<IEventQueueCallback> callback,
+        sp<::android::Looper> looper,
+        sp<::android::SensorEventQueue> internalQueue)
+            : mLooper(looper),
+              mInternalQueue(internalQueue) {
+
+    mLooper->addFd(mInternalQueue->getFd(), ALOOPER_POLL_CALLBACK, ALOOPER_EVENT_INPUT,
+            new EventQueueLooperCallback(this, callback), NULL /* data */);
+}
+
+EventQueue::~EventQueue() {
+    mLooper->removeFd(mInternalQueue->getFd());
+}
+
+// Methods from ::android::frameworks::sensorservice::V1_0::IEventQueue follow.
+Return<Result> EventQueue::enableSensor(int32_t sensorHandle, int32_t samplingPeriodUs,
+        int64_t maxBatchReportLatencyUs) {
+    // TODO implement
+    return convertResult(mInternalQueue->enableSensor(sensorHandle, samplingPeriodUs,
+            maxBatchReportLatencyUs, 0 /* reserved flags */));
+}
+
+Return<Result> EventQueue::disableSensor(int32_t sensorHandle) {
+    return convertResult(mInternalQueue->disableSensor(sensorHandle));
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace sensorservice
+}  // namespace frameworks
+}  // namespace android
diff --git a/services/sensorservice/hidl/EventQueue.h b/services/sensorservice/hidl/EventQueue.h
new file mode 100644
index 0000000..87c614b
--- /dev/null
+++ b/services/sensorservice/hidl/EventQueue.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_EVENTQUEUE_H
+#define ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_EVENTQUEUE_H
+
+#include "SensorManager.h"
+
+#include <android/frameworks/sensorservice/1.0/IEventQueue.h>
+#include <android/frameworks/sensorservice/1.0/IEventQueueCallback.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <sensor/SensorManager.h>
+
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::frameworks::sensorservice::V1_0::IEventQueue;
+using ::android::frameworks::sensorservice::V1_0::IEventQueueCallback;
+using ::android::frameworks::sensorservice::V1_0::Result;
+using ::android::hardware::Return;
+using ::android::sp;
+
+struct EventQueue final : public IEventQueue {
+    EventQueue(
+        sp<IEventQueueCallback> callback,
+        sp<::android::Looper> looper,
+        sp<::android::SensorEventQueue> internalQueue);
+    ~EventQueue();
+
+    // Methods from ::android::frameworks::sensorservice::V1_0::IEventQueue follow.
+    Return<Result> enableSensor(int32_t sensorHandle, int32_t samplingPeriodUs, int64_t maxBatchReportLatencyUs) override;
+    Return<Result> disableSensor(int32_t sensorHandle) override;
+
+private:
+    friend class EventQueueLooperCallback;
+    sp<::android::Looper> mLooper;
+    sp<::android::SensorEventQueue> mInternalQueue;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace sensorservice
+}  // namespace frameworks
+}  // namespace android
+
+#endif  // ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_EVENTQUEUE_H
diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp
index 576fcb5..00a7799 100644
--- a/services/sensorservice/hidl/SensorManager.cpp
+++ b/services/sensorservice/hidl/SensorManager.cpp
@@ -20,10 +20,14 @@
 #endif
 #include <android-base/logging.h>
 
-#include "DirectReportChannel.h"
 #include "SensorManager.h"
+
+#include "EventQueue.h"
+#include "DirectReportChannel.h"
 #include "utils.h"
 
+#include <thread>
+
 namespace android {
 namespace frameworks {
 namespace sensorservice {
@@ -40,6 +44,14 @@
             String16(ISensorManager::descriptor))} {
 }
 
+SensorManager::~SensorManager() {
+    // Stops pollAll inside the thread.
+    std::unique_lock<std::mutex> lock(mLooperMutex);
+    if (mLooper != nullptr) {
+        mLooper->wake();
+    }
+}
+
 // Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
 Return<void> SensorManager::getSensorList(getSensorList_cb _hidl_cb) {
     ::android::Sensor const* const* list;
@@ -111,10 +123,47 @@
     return Void();
 }
 
+/* One global looper for all event queues created from this SensorManager. */
+sp<::android::Looper> SensorManager::getLooper() {
+    std::unique_lock<std::mutex> lock(mLooperMutex);
+    if (mLooper == nullptr) {
+        std::condition_variable looperSet;
+
+        std::thread{[&mutex = mLooperMutex, &looper = mLooper, &looperSet] {
+            std::unique_lock<std::mutex> lock(mutex);
+            looper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS /* opts */);
+            lock.unlock();
+
+            looperSet.notify_one();
+            int pollResult = looper->pollAll(-1 /* timeout */);
+            if (pollResult != ALOOPER_POLL_WAKE) {
+                LOG(ERROR) << "Looper::pollAll returns unexpected " << pollResult;
+            }
+            LOG(INFO) << "Looper thread is terminated.";
+        }}.detach();
+        looperSet.wait(lock, [this]{ return this->mLooper != nullptr; });
+    }
+    return mLooper;
+}
+
 Return<void> SensorManager::createEventQueue(
-        __unused const sp<IEventQueueCallback> &callback, createEventQueue_cb _hidl_cb) {
-    // TODO(b/35219747) Implement this
-    _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
+        const sp<IEventQueueCallback> &callback, createEventQueue_cb _hidl_cb) {
+    if (callback == nullptr) {
+        _hidl_cb(nullptr, Result::BAD_VALUE);
+        return Void();
+    }
+
+    sp<::android::Looper> looper = getLooper();
+    sp<::android::SensorEventQueue> internalQueue = mInternalManager.createEventQueue();
+    if (internalQueue == nullptr) {
+        LOG(WARNING) << "::android::SensorManager::createEventQueue returns nullptr.";
+        _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
+        return Void();
+    }
+
+    sp<IEventQueue> queue = new EventQueue(callback, looper, internalQueue);
+    _hidl_cb(queue, Result::OK);
+
     return Void();
 }
 
diff --git a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
index 4d70b2d..edb112f 100644
--- a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
+++ b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
@@ -17,11 +17,14 @@
 #ifndef ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_SENSORMANAGER_H
 #define ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_SENSORMANAGER_H
 
+#include <mutex>
+
 #include <android/frameworks/sensorservice/1.0/ISensorManager.h>
 #include <android/frameworks/sensorservice/1.0/types.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 #include <sensor/SensorManager.h>
+#include <utils/Looper.h>
 
 namespace android {
 namespace frameworks {
@@ -37,6 +40,7 @@
 struct SensorManager : public ISensorManager {
 
     SensorManager();
+    ~SensorManager();
 
     // Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
     Return<void> getSensorList(getSensorList_cb _hidl_cb) override;
@@ -44,9 +48,13 @@
     Return<void> createAshmemDirectChannel(const hidl_memory& mem, uint64_t size, createAshmemDirectChannel_cb _hidl_cb) override;
     Return<void> createGrallocDirectChannel(const hidl_handle& buffer, uint64_t size, createGrallocDirectChannel_cb _hidl_cb) override;
     Return<void> createEventQueue(const sp<IEventQueueCallback> &callback, createEventQueue_cb _hidl_cb);
-private:
-    ::android::SensorManager& mInternalManager;
 
+private:
+    sp<::android::Looper> getLooper();
+
+    ::android::SensorManager& mInternalManager;
+    std::mutex mLooperMutex;
+    sp<::android::Looper> mLooper;
 };
 
 }  // namespace implementation
diff --git a/services/sensorservice/hidl/utils.cpp b/services/sensorservice/hidl/utils.cpp
index 4e02741..b540525 100644
--- a/services/sensorservice/hidl/utils.cpp
+++ b/services/sensorservice/hidl/utils.cpp
@@ -16,6 +16,8 @@
 
 #include "utils.h"
 
+#include <sensors/convert.h>
+
 namespace android {
 namespace frameworks {
 namespace sensorservice {
@@ -26,7 +28,7 @@
 using ::android::hardware::hidl_string;
 using ::android::hardware::sensors::V1_0::SensorInfo;
 
-SensorInfo convertSensor(const Sensor &src) {
+SensorInfo convertSensor(const Sensor& src) {
     SensorInfo dst;
     const String8& name = src.getName();
     const String8& vendor = src.getVendor();
@@ -36,7 +38,7 @@
     dst.sensorHandle = src.getHandle();
     dst.type = static_cast<::android::hardware::sensors::V1_0::SensorType>(
             src.getType());
-    // FIXME maxRange uses maxValue because ::android::Sensor wraps the
+    // maxRange uses maxValue because ::android::Sensor wraps the
     // internal sensor_t in this way.
     dst.maxRange = src.getMaxValue();
     dst.resolution = src.getResolution();
@@ -70,6 +72,13 @@
     }
 }
 
+::android::hardware::sensors::V1_0::Event convertEvent(const ::ASensorEvent& src) {
+    ::android::hardware::sensors::V1_0::Event dst;
+    ::android::hardware::sensors::V1_0::implementation::convertFromSensorEvent(
+            reinterpret_cast<const sensors_event_t&>(src), &dst);
+    return dst;
+}
+
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace sensorservice
diff --git a/services/sensorservice/hidl/utils.h b/services/sensorservice/hidl/utils.h
index 0606e69..b350928 100644
--- a/services/sensorservice/hidl/utils.h
+++ b/services/sensorservice/hidl/utils.h
@@ -30,6 +30,8 @@
 ::android::hardware::sensors::V1_0::SensorInfo convertSensor(const ::android::Sensor &src);
 Result convertResult(status_t status);
 
+::android::hardware::sensors::V1_0::Event convertEvent(const ::ASensorEvent &event);
+
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace sensorservice