Bug 1413362 - part 1: Add GeckoVRManager to support GVR WebVR implementation on Android draft
authorRandall Barker <rbarker@mozilla.com>
Tue, 31 Oct 2017 16:40:41 -0700
changeset 690449 560f1ecbc4d72af8f5006ff02ad0e7b2a94f3d47
parent 690147 3824edc9c490d29d9ebf13be01689b4f69fed40a
child 690450 1dbdf9f4cd57c8b3d91ac442103e3281a6dd8904
child 690465 8dd5a5447e1d20b68de209c68249134c8fe516f8
push id87299
push userbmo:rbarker@mozilla.com
push dateWed, 01 Nov 2017 23:52:00 +0000
bugs1413362
milestone58.0a1
Bug 1413362 - part 1: Add GeckoVRManager to support GVR WebVR implementation on Android MozReview-Commit-ID: C7XTF8N1W9a
mobile/android/base/moz.build
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoVRManager.java
widget/android/AndroidBridge.cpp
widget/android/GeckoVRManager.cpp
widget/android/GeckoVRManager.h
widget/android/GeneratedJNINatives.h
widget/android/GeneratedJNIWrappers.cpp
widget/android/GeneratedJNIWrappers.h
widget/android/moz.build
widget/android/nsAppShell.cpp
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -385,16 +385,17 @@ gvjar.sources += [geckoview_source_dir +
     'GeckoProfile.java',
     'GeckoProfileDirectories.java',
     'GeckoScreenOrientation.java',
     'GeckoSharedPrefs.java',
     'GeckoThread.java',
     'GeckoView.java',
     'GeckoViewHandler.java',
     'GeckoViewSettings.java',
+    'GeckoVRManager.java',
     'gfx/BitmapUtils.java',
     'gfx/BufferedImage.java',
     'gfx/BufferedImageGLInfo.java',
     'gfx/DynamicToolbarAnimator.java',
     'gfx/FloatSize.java',
     'gfx/FullScreenState.java',
     'gfx/GeckoLayerClient.java',
     'gfx/GeckoSurface.java',
new file mode 100644
--- /dev/null
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoVRManager.java
@@ -0,0 +1,137 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * vim: ts=4 sw=4 expandtab:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko;
+
+import org.mozilla.gecko.annotation.WrapForJNI;
+import org.mozilla.gecko.util.ThreadUtils;
+
+public class GeckoVRManager {
+     /**
+      * GeckoView applications implement this interface to provide GVR support for WebVR.
+      */
+     public interface GVRDelegate {
+         /**
+          * Creates non-presenting context. Will be invoked in the compositor thread.
+          */
+         long createGVRNonPresentingContext();
+         /**
+          * Destroys non-presenting context. Will be invoked in the compositor thread.
+          */
+         void destroyGVRNonPresentingContext();
+         /**
+          * Called when WebVR needs a presenting context. Will be invoked in the UI thread.
+          */
+         boolean enableVRMode();
+         /**
+          * Called when WebVR has finished presenting. Will be invoked in the UI thread.
+          */
+         void disableVRMode();
+     }
+
+    private static GVRDelegate mGVRDelegate;
+
+    /**
+     * Set the GVR Delegate for GeckoView.
+     * @param delegate GVRDelegate instance or null to unset.
+     */
+    public static void setGVRDelegate(GVRDelegate delegate) {
+        mGVRDelegate = delegate;
+    }
+
+    /**
+     * Set the GVR paused state.
+     * @param aPaused True if the application is being paused, False if the
+     * application is resuming.
+     */
+    public static void setGVRPaused(final boolean aPaused) {
+        nativeSetGVRPaused(aPaused);
+    }
+
+    /**
+     * Set the GVR presenting context.
+     * @param aContext GVR context to use when WebVR starts to present. Pass in
+     * zero to stop presenting.
+     */
+    public static void setGVRPresentingContext(final long aContext) {
+        nativeSetGVRPresentingContext(aContext);
+    }
+
+    /**
+     * Inform WebVR that the non-presenting context needs to be destroyed.
+     */
+    public static void cleanupGVRNonPresentingContext() {
+        nativeCleanupGVRNonPresentingContext();
+    }
+
+    @WrapForJNI
+    private static boolean isGVRPresent() {
+        return mGVRDelegate != null;
+    }
+
+    @WrapForJNI
+    private static long createGVRNonPresentingContext() {
+        if (mGVRDelegate == null) {
+            return 0;
+        }
+        return mGVRDelegate.createGVRNonPresentingContext();
+    }
+
+    @WrapForJNI
+    private static void destroyGVRNonPresentingContext() {
+        if (mGVRDelegate == null) {
+            return;
+        }
+        mGVRDelegate.destroyGVRNonPresentingContext();
+    }
+
+    @WrapForJNI
+    private static void enableVRMode() {
+        if (!ThreadUtils.isOnUiThread()) {
+            ThreadUtils.postToUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    enableVRMode();
+                }
+            });
+            return;
+        }
+
+        if (mGVRDelegate == null) {
+            return;
+        }
+
+        mGVRDelegate.enableVRMode();
+    }
+
+    @WrapForJNI
+    private static void disableVRMode() {
+        if (!ThreadUtils.isOnUiThread()) {
+            ThreadUtils.postToUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    disableVRMode();
+                }
+            });
+            return;
+        }
+
+        if (mGVRDelegate == null) {
+            return;
+        }
+
+        mGVRDelegate.disableVRMode();
+    }
+
+    @WrapForJNI(calledFrom = "ui")
+    static native void nativeSetGVRPresentingContext(final long aContext);
+
+    @WrapForJNI(calledFrom = "ui")
+    static native void nativeCleanupGVRNonPresentingContext();
+
+    @WrapForJNI(calledFrom = "ui")
+    static native void nativeSetGVRPaused(final boolean paused);
+}
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -55,16 +55,20 @@
 
 #include "FennecJNIWrappers.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::jni;
 using namespace mozilla::java;
 
+#if defined(MOZ_USE_GVR_ANDROID)
+extern bool SetupGVRJNI(JNIEnv* env);
+#endif // MOZ_USE_GVR_ANDROID
+
 AndroidBridge* AndroidBridge::sBridge = nullptr;
 static jobject sGlobalContext = nullptr;
 nsDataHashtable<nsStringHashKey, nsString> AndroidBridge::sStoragePaths;
 
 jmethodID AndroidBridge::GetMethodID(JNIEnv* env, jclass jClass,
                               const char* methodName, const char* methodType)
 {
    jmethodID methodID = env->GetMethodID(jClass, methodName, methodType);
@@ -181,16 +185,20 @@ AndroidBridge::AndroidBridge()
     AutoJNIClass readableByteChannel(jEnv, "java/nio/channels/ReadableByteChannel");
     jReadableByteChannel = readableByteChannel.getGlobalRef();
     jByteBufferRead = readableByteChannel.getMethod("read", "(Ljava/nio/ByteBuffer;)I");
 
     AutoJNIClass inputStream(jEnv, "java/io/InputStream");
     jInputStream = inputStream.getGlobalRef();
     jClose = inputStream.getMethod("close", "()V");
     jAvailable = inputStream.getMethod("available", "()I");
+
+#if defined(MOZ_USE_GVR_ANDROID)
+    SetupGVRJNI(jEnv);
+#endif // MOZ_USE_GVR_ANDROID
 }
 
 // Raw JNIEnv variants.
 jstring AndroidBridge::NewJavaString(JNIEnv* env, const char16_t* string, uint32_t len) {
    jstring ret = env->NewString(reinterpret_cast<const jchar*>(string), len);
    if (env->ExceptionCheck()) {
        ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
        env->ExceptionDescribe();
new file mode 100644
--- /dev/null
+++ b/widget/android/GeckoVRManager.cpp
@@ -0,0 +1,63 @@
+#include "GeckoVRManager.h"
+
+#if defined(MOZ_USE_GVR_ANDROID)
+#include "gfxVRGVRAPI.h"
+#endif // defined(MOZ_USE_GVR_ANDROID)
+
+namespace mozilla {
+
+void
+GeckoVRManager::NativeSetGVRPresentingContext(const int64_t aContext)
+{
+#if defined(MOZ_USE_GVR_ANDROID)
+  mozilla::gfx::SetGVRPresentingContext((void*)aContext);
+#endif // defined(MOZ_USE_GVR_ANDROID)
+}
+
+void
+GeckoVRManager::NativeCleanupGVRNonPresentingContext()
+{
+#if defined(MOZ_USE_GVR_ANDROID)
+  mozilla::gfx::CleanupGVRNonPresentingContext();
+#endif // defined(MOZ_USE_GVR_ANDROID)
+}
+
+void
+GeckoVRManager::NativeSetGVRPaused(const bool aPaused)
+{
+#if defined(MOZ_USE_GVR_ANDROID)
+  mozilla::gfx::SetGVRPaused(aPaused);
+#endif // defined(MOZ_USE_GVR_ANDROID)
+}
+
+void*
+GeckoVRManager::CreateGVRNonPresentingContext()
+{
+  return (void*)mozilla::java::GeckoVRManager::CreateGVRNonPresentingContext();
+}
+
+void
+GeckoVRManager::DestroyGVRNonPresentingContext()
+{
+  mozilla::java::GeckoVRManager::DestroyGVRNonPresentingContext();
+}
+
+void
+GeckoVRManager::EnableVRMode()
+{
+  mozilla::java::GeckoVRManager::EnableVRMode();
+}
+
+void
+GeckoVRManager::DisableVRMode()
+{
+  mozilla::java::GeckoVRManager::DisableVRMode();
+}
+
+bool
+GeckoVRManager::IsGVRPresent()
+{
+  return mozilla::java::GeckoVRManager::IsGVRPresent();
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/widget/android/GeckoVRManager.h
@@ -0,0 +1,25 @@
+#ifndef GeckoVRManager_h_
+#define GeckoVRManager_h_
+
+#include "GeneratedJNINatives.h"
+
+namespace mozilla {
+
+class GeckoVRManager
+    : public mozilla::java::GeckoVRManager::Natives<mozilla::GeckoVRManager>
+{
+
+public:
+  static void NativeSetGVRPresentingContext(const int64_t aContext);
+  static void NativeCleanupGVRNonPresentingContext();
+  static void NativeSetGVRPaused(const bool aPaused);
+  static void* CreateGVRNonPresentingContext();
+  static void DestroyGVRNonPresentingContext();
+  static void EnableVRMode();
+  static void DisableVRMode();
+  static bool IsGVRPresent();
+};
+
+} // namespace mozilla
+
+#endif // GeckoVRManager_h_
--- a/widget/android/GeneratedJNINatives.h
+++ b/widget/android/GeneratedJNINatives.h
@@ -253,16 +253,39 @@ const JNINativeMethod GeckoThread::Nativ
             ::template Wrap<&Impl::SpeculativeConnect>),
 
     mozilla::jni::MakeNativeMethod<GeckoThread::WaitOnGecko_t>(
             mozilla::jni::NativeStub<GeckoThread::WaitOnGecko_t, Impl>
             ::template Wrap<&Impl::WaitOnGecko>)
 };
 
 template<class Impl>
+class GeckoVRManager::Natives : public mozilla::jni::NativeImpl<GeckoVRManager, Impl>
+{
+public:
+    static const JNINativeMethod methods[3];
+};
+
+template<class Impl>
+const JNINativeMethod GeckoVRManager::Natives<Impl>::methods[] = {
+
+    mozilla::jni::MakeNativeMethod<GeckoVRManager::NativeCleanupGVRNonPresentingContext_t>(
+            mozilla::jni::NativeStub<GeckoVRManager::NativeCleanupGVRNonPresentingContext_t, Impl>
+            ::template Wrap<&Impl::NativeCleanupGVRNonPresentingContext>),
+
+    mozilla::jni::MakeNativeMethod<GeckoVRManager::NativeSetGVRPaused_t>(
+            mozilla::jni::NativeStub<GeckoVRManager::NativeSetGVRPaused_t, Impl>
+            ::template Wrap<&Impl::NativeSetGVRPaused>),
+
+    mozilla::jni::MakeNativeMethod<GeckoVRManager::NativeSetGVRPresentingContext_t>(
+            mozilla::jni::NativeStub<GeckoVRManager::NativeSetGVRPresentingContext_t, Impl>
+            ::template Wrap<&Impl::NativeSetGVRPresentingContext>)
+};
+
+template<class Impl>
 class GeckoView::Window::Natives : public mozilla::jni::NativeImpl<Window, Impl>
 {
 public:
     static const JNINativeMethod methods[5];
 };
 
 template<class Impl>
 const JNINativeMethod GeckoView::Window::Natives<Impl>::methods[] = {
--- a/widget/android/GeneratedJNIWrappers.cpp
+++ b/widget/android/GeneratedJNIWrappers.cpp
@@ -910,16 +910,68 @@ auto GeckoThread::State::RESTARTING() ->
 constexpr char GeckoThread::State::RUNNING_t::name[];
 constexpr char GeckoThread::State::RUNNING_t::signature[];
 
 auto GeckoThread::State::RUNNING() -> State::LocalRef
 {
     return mozilla::jni::Field<RUNNING_t>::Get(State::Context(), nullptr);
 }
 
+const char GeckoVRManager::name[] =
+        "org/mozilla/gecko/GeckoVRManager";
+
+constexpr char GeckoVRManager::CreateGVRNonPresentingContext_t::name[];
+constexpr char GeckoVRManager::CreateGVRNonPresentingContext_t::signature[];
+
+auto GeckoVRManager::CreateGVRNonPresentingContext() -> int64_t
+{
+    return mozilla::jni::Method<CreateGVRNonPresentingContext_t>::Call(GeckoVRManager::Context(), nullptr);
+}
+
+constexpr char GeckoVRManager::DestroyGVRNonPresentingContext_t::name[];
+constexpr char GeckoVRManager::DestroyGVRNonPresentingContext_t::signature[];
+
+auto GeckoVRManager::DestroyGVRNonPresentingContext() -> void
+{
+    return mozilla::jni::Method<DestroyGVRNonPresentingContext_t>::Call(GeckoVRManager::Context(), nullptr);
+}
+
+constexpr char GeckoVRManager::DisableVRMode_t::name[];
+constexpr char GeckoVRManager::DisableVRMode_t::signature[];
+
+auto GeckoVRManager::DisableVRMode() -> void
+{
+    return mozilla::jni::Method<DisableVRMode_t>::Call(GeckoVRManager::Context(), nullptr);
+}
+
+constexpr char GeckoVRManager::EnableVRMode_t::name[];
+constexpr char GeckoVRManager::EnableVRMode_t::signature[];
+
+auto GeckoVRManager::EnableVRMode() -> void
+{
+    return mozilla::jni::Method<EnableVRMode_t>::Call(GeckoVRManager::Context(), nullptr);
+}
+
+constexpr char GeckoVRManager::IsGVRPresent_t::name[];
+constexpr char GeckoVRManager::IsGVRPresent_t::signature[];
+
+auto GeckoVRManager::IsGVRPresent() -> bool
+{
+    return mozilla::jni::Method<IsGVRPresent_t>::Call(GeckoVRManager::Context(), nullptr);
+}
+
+constexpr char GeckoVRManager::NativeCleanupGVRNonPresentingContext_t::name[];
+constexpr char GeckoVRManager::NativeCleanupGVRNonPresentingContext_t::signature[];
+
+constexpr char GeckoVRManager::NativeSetGVRPaused_t::name[];
+constexpr char GeckoVRManager::NativeSetGVRPaused_t::signature[];
+
+constexpr char GeckoVRManager::NativeSetGVRPresentingContext_t::name[];
+constexpr char GeckoVRManager::NativeSetGVRPresentingContext_t::signature[];
+
 const char GeckoView::name[] =
         "org/mozilla/gecko/GeckoView";
 
 const char GeckoView::State::name[] =
         "org/mozilla/gecko/GeckoView$State";
 
 constexpr char GeckoView::State::INITIAL_t::name[];
 constexpr char GeckoView::State::INITIAL_t::signature[];
--- a/widget/android/GeneratedJNIWrappers.h
+++ b/widget/android/GeneratedJNIWrappers.h
@@ -2728,16 +2728,177 @@ public:
 
     static auto RUNNING() -> State::LocalRef;
 
     static const mozilla::jni::CallingThread callingThread =
             mozilla::jni::CallingThread::ANY;
 
 };
 
+class GeckoVRManager : public mozilla::jni::ObjectBase<GeckoVRManager>
+{
+public:
+    static const char name[];
+
+    explicit GeckoVRManager(const Context& ctx) : ObjectBase<GeckoVRManager>(ctx) {}
+
+    struct CreateGVRNonPresentingContext_t {
+        typedef GeckoVRManager Owner;
+        typedef int64_t ReturnType;
+        typedef int64_t SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "createGVRNonPresentingContext";
+        static constexpr char signature[] =
+                "()J";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::ANY;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static auto CreateGVRNonPresentingContext() -> int64_t;
+
+    struct DestroyGVRNonPresentingContext_t {
+        typedef GeckoVRManager Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "destroyGVRNonPresentingContext";
+        static constexpr char signature[] =
+                "()V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::ANY;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static auto DestroyGVRNonPresentingContext() -> void;
+
+    struct DisableVRMode_t {
+        typedef GeckoVRManager Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "disableVRMode";
+        static constexpr char signature[] =
+                "()V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::ANY;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static auto DisableVRMode() -> void;
+
+    struct EnableVRMode_t {
+        typedef GeckoVRManager Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "enableVRMode";
+        static constexpr char signature[] =
+                "()V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::ANY;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static auto EnableVRMode() -> void;
+
+    struct IsGVRPresent_t {
+        typedef GeckoVRManager Owner;
+        typedef bool ReturnType;
+        typedef bool SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "isGVRPresent";
+        static constexpr char signature[] =
+                "()Z";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::ANY;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static auto IsGVRPresent() -> bool;
+
+    struct NativeCleanupGVRNonPresentingContext_t {
+        typedef GeckoVRManager Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "nativeCleanupGVRNonPresentingContext";
+        static constexpr char signature[] =
+                "()V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::UI;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    struct NativeSetGVRPaused_t {
+        typedef GeckoVRManager Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<
+                bool> Args;
+        static constexpr char name[] = "nativeSetGVRPaused";
+        static constexpr char signature[] =
+                "(Z)V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::UI;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    struct NativeSetGVRPresentingContext_t {
+        typedef GeckoVRManager Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<
+                int64_t> Args;
+        static constexpr char name[] = "nativeSetGVRPresentingContext";
+        static constexpr char signature[] =
+                "(J)V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::UI;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static const mozilla::jni::CallingThread callingThread =
+            mozilla::jni::CallingThread::ANY;
+
+    template<class Impl> class Natives;
+};
+
 class GeckoView : public mozilla::jni::ObjectBase<GeckoView>
 {
 public:
     static const char name[];
 
     explicit GeckoView(const Context& ctx) : ObjectBase<GeckoView>(ctx) {}
 
     class State;
--- a/widget/android/moz.build
+++ b/widget/android/moz.build
@@ -42,16 +42,17 @@ UNIFIED_SOURCES += [
     'AndroidContentController.cpp',
     'AndroidJavaWrappers.cpp',
     'AndroidJNI.cpp',
     'AndroidJNIWrapper.cpp',
     'AndroidUiThread.cpp',
     'ANRReporter.cpp',
     'EventDispatcher.cpp',
     'GeckoEditableSupport.cpp',
+    'GeckoVRManager.cpp',
     'GeneratedJNIWrappers.cpp',
     'GfxInfo.cpp',
     'nsAndroidProtocolHandler.cpp',
     'nsAppShell.cpp',
     'nsClipboard.cpp',
     'nsDeviceContextAndroid.cpp',
     'nsIdleServiceAndroid.cpp',
     'nsLookAndFeel.cpp',
@@ -66,16 +67,17 @@ include('/ipc/chromium/chromium-config.m
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
     '/dom/system/android',
     '/gfx/2d',
+    '/gfx/vr',
     '/layout/painting',
     '/netwerk/base',
     '/netwerk/cache',
     '/widget',
     '/xpcom/threads',
 ]
 
 CXXFLAGS += ['-Wno-error=shadow']
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -64,16 +64,17 @@
 
 #include "AndroidAlerts.h"
 #include "AndroidUiThread.h"
 #include "ANRReporter.h"
 #include "GeckoBatteryManager.h"
 #include "GeckoNetworkManager.h"
 #include "GeckoProcessManager.h"
 #include "GeckoScreenOrientation.h"
+#include "GeckoVRManager.h"
 #include "PrefsHelper.h"
 #include "fennec/MemoryMonitor.h"
 #include "fennec/Telemetry.h"
 #include "fennec/ThumbnailHelper.h"
 
 #ifdef DEBUG_ANDROID_EVENTS
 #define EVLOG(args...)  ALOG(args)
 #else
@@ -402,16 +403,17 @@ nsAppShell::nsAppShell()
         AndroidBridge::ConstructBridge();
         GeckoAppShellSupport::Init();
         GeckoThreadSupport::Init();
         mozilla::GeckoBatteryManager::Init();
         mozilla::GeckoNetworkManager::Init();
         mozilla::GeckoProcessManager::Init();
         mozilla::GeckoScreenOrientation::Init();
         mozilla::PrefsHelper::Init();
+        mozilla::GeckoVRManager::Init();
         nsWindow::InitNatives();
 
         if (jni::IsFennec()) {
             mozilla::ANRReporter::Init();
             mozilla::MemoryMonitor::Init();
             mozilla::widget::Telemetry::Init();
             mozilla::ThumbnailHelper::Init();
         }