1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/android/vr/vr_shell_delegate.h"
6
7 #include <utility>
8
9 #include "base/android/jni_android.h"
10 #include "base/bind.h"
11 #include "chrome/android/features/vr/jni_headers/VrShellDelegate_jni.h"
12 #include "chrome/browser/android/vr/vr_shell.h"
13 #include "chrome/browser/android/vr/vrcore_install_helper.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/component_updater/vr_assets_component_installer.h"
16 #include "chrome/browser/vr/assets_loader.h"
17 #include "content/public/browser/browser_xr_runtime.h"
18 #include "content/public/browser/xr_runtime_manager.h"
19 #include "device/vr/android/gvr/gvr_delegate_provider_factory.h"
20 #include "device/vr/android/gvr/gvr_device.h"
21 #include "device/vr/buildflags/buildflags.h"
22 #include "device/vr/public/mojom/vr_service.mojom.h"
23 #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr.h"
24
25 using base::android::AttachCurrentThread;
26 using base::android::JavaParamRef;
27 using base::android::JavaRef;
28 using base::android::ScopedJavaLocalRef;
29
30 namespace vr {
31
32 namespace {
33
34 class VrShellDelegateProviderFactory
35 : public device::GvrDelegateProviderFactory {
36 public:
37 VrShellDelegateProviderFactory() = default;
38 ~VrShellDelegateProviderFactory() override = default;
39 device::GvrDelegateProvider* CreateGvrDelegateProvider() override;
40
41 private:
42 DISALLOW_COPY_AND_ASSIGN(VrShellDelegateProviderFactory);
43 };
44
45 device::GvrDelegateProvider*
CreateGvrDelegateProvider()46 VrShellDelegateProviderFactory::CreateGvrDelegateProvider() {
47 return VrShellDelegate::CreateVrShellDelegate();
48 }
49
50 } // namespace
51
VrShellDelegate(JNIEnv * env,jobject obj)52 VrShellDelegate::VrShellDelegate(JNIEnv* env, jobject obj)
53 : task_runner_(base::ThreadTaskRunnerHandle::Get()) {
54 DVLOG(1) << __FUNCTION__ << "=" << this;
55 j_vr_shell_delegate_.Reset(env, obj);
56 }
57
~VrShellDelegate()58 VrShellDelegate::~VrShellDelegate() {
59 DVLOG(1) << __FUNCTION__ << "=" << this;
60 device::GvrDevice* gvr_device = GetGvrDevice();
61 if (gvr_device)
62 gvr_device->OnExitPresent();
63 if (!on_present_result_callback_.is_null())
64 std::move(on_present_result_callback_).Run(false);
65 }
66
CreateVrShellDelegate()67 device::GvrDelegateProvider* VrShellDelegate::CreateVrShellDelegate() {
68 JNIEnv* env = AttachCurrentThread();
69 ScopedJavaLocalRef<jobject> jdelegate = Java_VrShellDelegate_getInstance(env);
70 if (!jdelegate.is_null())
71 return GetNativeVrShellDelegate(env, jdelegate);
72 return nullptr;
73 }
74
GetNativeVrShellDelegate(JNIEnv * env,const JavaRef<jobject> & jdelegate)75 VrShellDelegate* VrShellDelegate::GetNativeVrShellDelegate(
76 JNIEnv* env,
77 const JavaRef<jobject>& jdelegate) {
78 return reinterpret_cast<VrShellDelegate*>(
79 Java_VrShellDelegate_getNativePointer(env, jdelegate));
80 }
81
SetDelegate(VrShell * vr_shell)82 void VrShellDelegate::SetDelegate(VrShell* vr_shell) {
83 vr_shell_ = vr_shell;
84
85 if (pending_successful_present_request_) {
86 CHECK(!on_present_result_callback_.is_null());
87 pending_successful_present_request_ = false;
88 std::move(on_present_result_callback_).Run(true);
89 }
90 }
91
RemoveDelegate()92 void VrShellDelegate::RemoveDelegate() {
93 vr_shell_ = nullptr;
94 if (pending_successful_present_request_) {
95 CHECK(!on_present_result_callback_.is_null());
96 pending_successful_present_request_ = false;
97 std::move(on_present_result_callback_).Run(false);
98 }
99
100 device::GvrDevice* gvr_device = GetGvrDevice();
101 if (gvr_device)
102 gvr_device->OnExitPresent();
103 }
104
SetPresentResult(JNIEnv * env,const JavaParamRef<jobject> & obj,jboolean success)105 void VrShellDelegate::SetPresentResult(JNIEnv* env,
106 const JavaParamRef<jobject>& obj,
107 jboolean success) {
108 CHECK(!on_present_result_callback_.is_null());
109 std::move(on_present_result_callback_).Run(static_cast<bool>(success));
110 }
111
OnPresentResult(device::mojom::VRDisplayInfoPtr display_info,device::mojom::XRRuntimeSessionOptionsPtr options,base::OnceCallback<void (device::mojom::XRSessionPtr)> callback,bool success)112 void VrShellDelegate::OnPresentResult(
113 device::mojom::VRDisplayInfoPtr display_info,
114 device::mojom::XRRuntimeSessionOptionsPtr options,
115 base::OnceCallback<void(device::mojom::XRSessionPtr)> callback,
116 bool success) {
117 DVLOG(1) << __FUNCTION__ << ": success=" << success;
118 DCHECK(options);
119
120 DVLOG(3) << __func__ << ": options->required_features.size()="
121 << options->required_features.size()
122 << ", options->optional_features.size()="
123 << options->optional_features.size();
124
125 if (!success) {
126 std::move(callback).Run(nullptr);
127 return;
128 }
129
130 if (!vr_shell_) {
131 // We have to wait until the GL thread is ready since we have to get the
132 // XRPresentationClient.
133 pending_successful_present_request_ = true;
134 on_present_result_callback_ = base::BindOnce(
135 &VrShellDelegate::OnPresentResult, base::Unretained(this),
136 std::move(display_info), std::move(options), std::move(callback));
137 return;
138 }
139
140 DVLOG(1) << __FUNCTION__ << ": connecting presenting service";
141 request_present_response_callback_ = std::move(callback);
142 vr_shell_->ConnectPresentingService(std::move(display_info),
143 std::move(options));
144 }
145
SendRequestPresentReply(device::mojom::XRSessionPtr session)146 void VrShellDelegate::SendRequestPresentReply(
147 device::mojom::XRSessionPtr session) {
148 DVLOG(1) << __FUNCTION__;
149 if (!request_present_response_callback_) {
150 DLOG(ERROR) << __FUNCTION__ << ": ERROR: no callback";
151 return;
152 }
153
154 std::move(request_present_response_callback_).Run(std::move(session));
155 }
156
OnPause(JNIEnv * env,const JavaParamRef<jobject> & obj)157 void VrShellDelegate::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) {
158 if (vr_shell_)
159 return;
160 device::GvrDevice* gvr_device = GetGvrDevice();
161 if (gvr_device)
162 gvr_device->PauseTracking();
163 }
164
OnResume(JNIEnv * env,const JavaParamRef<jobject> & obj)165 void VrShellDelegate::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) {
166 if (vr_shell_)
167 return;
168 device::GvrDevice* gvr_device = GetGvrDevice();
169 if (gvr_device)
170 gvr_device->ResumeTracking();
171 }
172
Destroy(JNIEnv * env,const JavaParamRef<jobject> & obj)173 void VrShellDelegate::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) {
174 delete this;
175 }
176
ShouldDisableGvrDevice()177 bool VrShellDelegate::ShouldDisableGvrDevice() {
178 return VrCoreInstallHelper::VrSupportNeedsUpdate();
179 }
180
StartWebXRPresentation(device::mojom::VRDisplayInfoPtr display_info,device::mojom::XRRuntimeSessionOptionsPtr options,base::OnceCallback<void (device::mojom::XRSessionPtr)> callback)181 void VrShellDelegate::StartWebXRPresentation(
182 device::mojom::VRDisplayInfoPtr display_info,
183 device::mojom::XRRuntimeSessionOptionsPtr options,
184 base::OnceCallback<void(device::mojom::XRSessionPtr)> callback) {
185 if (!on_present_result_callback_.is_null() ||
186 !request_present_response_callback_.is_null()) {
187 // Can only handle one request at a time. This is also extremely unlikely to
188 // happen in practice.
189 std::move(callback).Run(nullptr);
190 return;
191 }
192
193 on_present_result_callback_ = base::BindOnce(
194 &VrShellDelegate::OnPresentResult, base::Unretained(this),
195 std::move(display_info), std::move(options), std::move(callback));
196
197 // If/When VRShell is ready for use it will call SetPresentResult.
198 JNIEnv* env = AttachCurrentThread();
199 Java_VrShellDelegate_presentRequested(env, j_vr_shell_delegate_);
200 }
201
ExitWebVRPresent()202 void VrShellDelegate::ExitWebVRPresent() {
203 JNIEnv* env = AttachCurrentThread();
204 Java_VrShellDelegate_exitWebVRPresent(env, j_vr_shell_delegate_);
205 device::GvrDevice* gvr_device = GetGvrDevice();
206 if (gvr_device)
207 gvr_device->OnExitPresent();
208 }
209
GetGvrDevice()210 device::GvrDevice* VrShellDelegate::GetGvrDevice() {
211 return device::GvrDelegateProviderFactory::GetDevice();
212 }
213
214 // ----------------------------------------------------------------------------
215 // Native JNI methods
216 // ----------------------------------------------------------------------------
217
JNI_VrShellDelegate_Init(JNIEnv * env,const JavaParamRef<jobject> & obj)218 jlong JNI_VrShellDelegate_Init(JNIEnv* env, const JavaParamRef<jobject>& obj) {
219 return reinterpret_cast<intptr_t>(new VrShellDelegate(env, obj));
220 }
221
JNI_VrShellDelegate_OnLibraryAvailable(JNIEnv * env)222 static void JNI_VrShellDelegate_OnLibraryAvailable(JNIEnv* env) {
223 device::GvrDelegateProviderFactory::Install(
224 std::make_unique<VrShellDelegateProviderFactory>());
225 }
226
JNI_VrShellDelegate_RegisterVrAssetsComponent(JNIEnv * env)227 static void JNI_VrShellDelegate_RegisterVrAssetsComponent(JNIEnv* env) {
228 component_updater::RegisterVrAssetsComponent(
229 g_browser_process->component_updater());
230 }
231
232 } // namespace vr
233