Connect VR HAL to VrManagerService.

- Implement lifecycle calls into HAL from VrManagerService.

Bug: 22855417
Change-Id: I7b8144621ffcd44470d0ed3e6b137fffb081a21a
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 2deb0d5..2f076d1 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -36,6 +36,9 @@
 
     public static final String TAG = "VrManagerService";
 
+    private static native void initializeNative();
+    private static native void setVrModeNative(boolean enabled);
+
     private final Object mLock = new Object();
     private boolean mVrModeEnabled = false;
     private ArraySet<VrStateListener> mListeners = new ArraySet<>();
@@ -68,6 +71,10 @@
 
     @Override
     public void onStart() {
+        synchronized(mLock) {
+            initializeNative();
+        }
+
         publishLocalService(VrManagerInternal.class, new LocalService());
     }
 
@@ -89,6 +96,7 @@
                 mVrModeEnabled = enabled;
                 // Log mode change event.
                 Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
+                setVrModeNative(mVrModeEnabled);
                 onVrModeChangedLocked();
             }
         }
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index d1b8648..bb571c3 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -28,6 +28,7 @@
     $(LOCAL_REL_DIR)/com_android_server_SerialService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_SystemServer.cpp \
     $(LOCAL_REL_DIR)/com_android_server_tv_TvInputHal.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_vr_VrManagerService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_UsbDeviceManager.cpp \
     $(LOCAL_REL_DIR)/com_android_server_UsbMidiDevice.cpp \
     $(LOCAL_REL_DIR)/com_android_server_UsbHostManager.cpp \
diff --git a/services/core/jni/com_android_server_vr_VrManagerService.cpp b/services/core/jni/com_android_server_vr_VrManagerService.cpp
new file mode 100644
index 0000000..1aba43b
--- /dev/null
+++ b/services/core/jni/com_android_server_vr_VrManagerService.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#define LOG_TAG "VrManagerService"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <jni.h>
+#include <JNIHelp.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/vr.h>
+
+namespace android {
+
+static vr_module_t *gVrHardwareModule = NULL;
+
+
+static void init_native(JNIEnv* /* env */, jclass /* clazz */) {
+    if (gVrHardwareModule != NULL) {
+        // This call path should never be hit.
+        ALOGE("%s: May not initialize VR hardware module more than once!", __FUNCTION__);
+        return;
+    }
+
+    int err = hw_get_module(VR_HARDWARE_MODULE_ID, (hw_module_t const**)&gVrHardwareModule);
+    if (err) {
+        ALOGW("%s: Could not open VR hardware module, error %s (%d).", __FUNCTION__,
+                strerror(-err), err);
+        return;
+    }
+
+    // Call init method if implemented.
+    if (gVrHardwareModule->init) {
+        gVrHardwareModule->init(gVrHardwareModule);
+    }
+}
+
+static void setVrMode_native(JNIEnv* /* env */, jclass /* clazz */, jboolean enabled) {
+    if (gVrHardwareModule == NULL) {
+        // There is no VR hardware module implemented, do nothing.
+        return;
+    }
+
+    // Call set_vr_mode method, this must be implemented if the HAL exists.
+    gVrHardwareModule->set_vr_mode(gVrHardwareModule, static_cast<bool>(enabled));
+}
+
+static const JNINativeMethod method_table[] = {
+    { "initializeNative", "()V", (void*)init_native },
+    { "setVrModeNative", "(Z)V", (void*)setVrMode_native },
+};
+
+int register_android_server_vr_VrManagerService(JNIEnv *env)
+{
+    return jniRegisterNativeMethods(env, "com/android/server/vr/VrManagerService",
+            method_table, NELEM(method_table));
+}
+
+}; // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index a7010bc..ef5c56c 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -35,6 +35,7 @@
 int register_android_server_UsbDeviceManager(JNIEnv* env);
 int register_android_server_UsbMidiDevice(JNIEnv* env);
 int register_android_server_UsbHostManager(JNIEnv* env);
+int register_android_server_vr_VrManagerService(JNIEnv* env);
 int register_android_server_VibratorService(JNIEnv* env);
 int register_android_server_location_GnssLocationProvider(JNIEnv* env);
 int register_android_server_location_FlpHardwareProvider(JNIEnv* env);
@@ -69,6 +70,7 @@
     register_android_server_UsbDeviceManager(env);
     register_android_server_UsbMidiDevice(env);
     register_android_server_UsbHostManager(env);
+    register_android_server_vr_VrManagerService(env);
     register_android_server_VibratorService(env);
     register_android_server_SystemServer(env);
     register_android_server_location_GnssLocationProvider(env);