SensorManager: attach background thread to JavaVM

Test: pass
Bug: 62404135

Change-Id: I63a128c3c933904211f5ff2483492674eaba93ed
diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp
index 991944e..004a5c5 100644
--- a/services/sensorservice/hidl/SensorManager.cpp
+++ b/services/sensorservice/hidl/SensorManager.cpp
@@ -42,7 +42,10 @@
 using ::android::hardware::Void;
 using ::android::sp;
 
-SensorManager::SensorManager() {
+static const char* POLL_THREAD_NAME = "hidl_ssvc_poll";
+
+SensorManager::SensorManager(JavaVM* vm)
+        : mJavaVm(vm) {
 }
 
 SensorManager::~SensorManager() {
@@ -130,7 +133,7 @@
     if (mLooper == nullptr) {
         std::condition_variable looperSet;
 
-        std::thread{[&mutex = mLooperMutex, &looper = mLooper, &looperSet] {
+        std::thread{[&mutex = mLooperMutex, &looper = mLooper, &looperSet, javaVm = mJavaVm] {
 
             struct sched_param p = {0};
             p.sched_priority = 10;
@@ -143,11 +146,28 @@
             looper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS /* opts */);
             lock.unlock();
 
+            // Attach the thread to JavaVM so that pollAll do not crash if the event
+            // is from Java.
+            JavaVMAttachArgs args{
+                .version = JNI_VERSION_1_2,
+                .name = POLL_THREAD_NAME,
+                .group = NULL
+            };
+            JNIEnv* env;
+            if (javaVm->AttachCurrentThread(&env, &args) != JNI_OK) {
+                LOG(FATAL) << "Cannot attach SensorManager looper thread to Java VM.";
+            }
+
             looperSet.notify_one();
             int pollResult = looper->pollAll(-1 /* timeout */);
             if (pollResult != ALOOPER_POLL_WAKE) {
                 LOG(ERROR) << "Looper::pollAll returns unexpected " << pollResult;
             }
+
+            if (javaVm->DetachCurrentThread() != JNI_OK) {
+                LOG(ERROR) << "Cannot detach SensorManager looper thread from Java VM.";
+            }
+
             LOG(INFO) << "Looper thread is terminated.";
         }}.detach();
         looperSet.wait(lock, [this]{ return this->mLooper != nullptr; });
diff --git a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
index cc044bf..e66c8e5 100644
--- a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
+++ b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_SENSORMANAGER_H
 #define ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_SENSORMANAGER_H
 
+#include <jni.h>
+
 #include <mutex>
 
 #include <android/frameworks/sensorservice/1.0/ISensorManager.h>
@@ -39,7 +41,7 @@
 
 struct SensorManager final : public ISensorManager {
 
-    SensorManager();
+    SensorManager(JavaVM* vm);
     ~SensorManager();
 
     // Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
@@ -59,6 +61,8 @@
 
     std::mutex mLooperMutex;
     sp<::android::Looper> mLooper;
+
+    JavaVM* mJavaVm;
 };
 
 }  // namespace implementation