OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.vr_shell; | 5 package org.chromium.chrome.browser.vr_shell; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.app.PendingIntent; | 8 import android.app.PendingIntent; |
9 import android.content.ComponentName; | 9 import android.content.ComponentName; |
10 import android.content.Intent; | 10 import android.content.Intent; |
(...skipping 22 matching lines...) Expand all Loading... | |
33 | 33 |
34 /** | 34 /** |
35 * Manages interactions with the VR Shell. | 35 * Manages interactions with the VR Shell. |
36 */ | 36 */ |
37 @JNINamespace("vr_shell") | 37 @JNINamespace("vr_shell") |
38 public class VrShellDelegate { | 38 public class VrShellDelegate { |
39 private static final String TAG = "VrShellDelegate"; | 39 private static final String TAG = "VrShellDelegate"; |
40 // Pseudo-random number to avoid request id collisions. | 40 // Pseudo-random number to avoid request id collisions. |
41 public static final int EXIT_VR_RESULT = 721251; | 41 public static final int EXIT_VR_RESULT = 721251; |
42 | 42 |
43 public static final int ENTER_VR_NOT_NECESSARY = 0; | |
Ted C
2016/11/16 22:20:51
For these, take a look at IntDef's as a way of mak
| |
44 public static final int ENTER_VR_CANCELLED = 1; | |
45 public static final int ENTER_VR_REQUESTED = 2; | |
46 | |
43 // TODO(bshe): These should be replaced by string provided by NDK. Currently , it only available | 47 // TODO(bshe): These should be replaced by string provided by NDK. Currently , it only available |
44 // in SDK and we don't want add dependency to SDK just to get these strings. | 48 // in SDK and we don't want add dependency to SDK just to get these strings. |
45 private static final String DAYDREAM_VR_EXTRA = "android.intent.extra.VR_LAU NCH"; | 49 private static final String DAYDREAM_VR_EXTRA = "android.intent.extra.VR_LAU NCH"; |
46 private static final String DAYDREAM_CATEGORY = "com.google.intent.category. DAYDREAM"; | 50 private static final String DAYDREAM_CATEGORY = "com.google.intent.category. DAYDREAM"; |
47 private static final String CARDBOARD_CATEGORY = "com.google.intent.category .CARDBOARD"; | 51 private static final String CARDBOARD_CATEGORY = "com.google.intent.category .CARDBOARD"; |
48 | 52 |
49 private static final String VR_ACTIVITY_ALIAS = | 53 private static final String VR_ACTIVITY_ALIAS = |
50 "org.chromium.chrome.browser.VRChromeTabbedActivity"; | 54 "org.chromium.chrome.browser.VRChromeTabbedActivity"; |
51 private static final String DAYDREAM_DON_TYPE = "DAYDREAM_DON_TYPE"; | |
52 | |
53 private static final int DAYDREAM_DON_TYPE_VR_SHELL = 0; | |
54 private static final int DAYDREAM_DON_TYPE_WEBVR = 1; | |
55 private static final int DAYDREAM_DON_TYPE_AUTO = 2; | |
56 | 55 |
57 private static final long REENTER_VR_TIMEOUT_MS = 1000; | 56 private static final long REENTER_VR_TIMEOUT_MS = 1000; |
58 | 57 |
59 private final ChromeTabbedActivity mActivity; | 58 private final ChromeTabbedActivity mActivity; |
60 private final TabObserver mTabObserver; | 59 private final TabObserver mTabObserver; |
60 private final Intent mEnterVRIntent; | |
61 | 61 |
62 private boolean mVrAvailable; | 62 private boolean mVrAvailable; |
63 private Boolean mVrShellEnabled; | 63 private Boolean mVrShellEnabled; |
64 | 64 |
65 private Class<? extends VrShell> mVrShellClass; | 65 private Class<? extends VrShell> mVrShellClass; |
66 private Class<? extends NonPresentingGvrContext> mNonPresentingGvrContextCla ss; | 66 private Class<? extends NonPresentingGvrContext> mNonPresentingGvrContextCla ss; |
67 private Class<? extends VrDaydreamApi> mVrDaydreamApiClass; | 67 private Class<? extends VrDaydreamApi> mVrDaydreamApiClass; |
68 private Class<? extends VrCoreVersionChecker> mVrCoreVersionCheckerClass; | 68 private Class<? extends VrCoreVersionChecker> mVrCoreVersionCheckerClass; |
69 private VrShell mVrShell; | 69 private VrShell mVrShell; |
70 private NonPresentingGvrContext mNonPresentingGvrContext; | 70 private NonPresentingGvrContext mNonPresentingGvrContext; |
71 private VrDaydreamApi mVrDaydreamApi; | 71 private VrDaydreamApi mVrDaydreamApi; |
72 private VrCoreVersionChecker mVrCoreVersionChecker; | 72 private VrCoreVersionChecker mVrCoreVersionChecker; |
73 private boolean mInVr; | 73 private boolean mInVr; |
74 private int mRestoreSystemUiVisibilityFlag = -1; | 74 private int mRestoreSystemUiVisibilityFlag = -1; |
75 private int mRestoreOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIE D; | 75 private int mRestoreOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIE D; |
76 private long mNativeVrShellDelegate; | 76 private long mNativeVrShellDelegate; |
77 private Tab mTab; | 77 private Tab mTab; |
78 private boolean mRequestedWebVR; | 78 private boolean mRequestedWebVR; |
79 private long mLastVRExit; | 79 private long mLastVRExit; |
80 | 80 |
81 public VrShellDelegate(ChromeTabbedActivity activity) { | 81 public VrShellDelegate(ChromeTabbedActivity activity) { |
82 mActivity = activity; | 82 mActivity = activity; |
83 mVrAvailable = maybeFindVrClasses() && isVrCoreCompatible(); | 83 mVrAvailable = maybeFindVrClasses() && isVrCoreCompatible() && createVrD aydreamApi(); |
84 createVrDaydreamApi(); | 84 if (mVrAvailable) { |
85 mEnterVRIntent = mVrDaydreamApi.createVrIntent( | |
86 new ComponentName(mActivity, VR_ACTIVITY_ALIAS)); | |
87 } else { | |
88 mEnterVRIntent = null; | |
89 } | |
85 mTabObserver = new EmptyTabObserver() { | 90 mTabObserver = new EmptyTabObserver() { |
86 @Override | 91 @Override |
87 public void onContentChanged(Tab tab) { | 92 public void onContentChanged(Tab tab) { |
88 if (tab.getNativePage() != null || tab.isShowingSadTab()) { | 93 if (tab.getNativePage() != null || tab.isShowingSadTab()) { |
89 // For now we don't handle native pages. crbug.com/661609 | 94 // For now we don't handle native pages. crbug.com/661609 |
90 exitVRIfNecessary(true); | 95 exitVRIfNecessary(true); |
91 } | 96 } |
92 } | 97 } |
93 | 98 |
94 @Override | 99 @Override |
95 public void onWebContentsSwapped(Tab tab, boolean didStartLoad, bool ean didFinishLoad) { | 100 public void onWebContentsSwapped(Tab tab, boolean didStartLoad, bool ean didFinishLoad) { |
96 // TODO(mthiesse): Update the native WebContents pointer and com positor. This | 101 // TODO(mthiesse): Update the native WebContents pointer and com positor. This |
97 // doesn't seem to get triggered in VR Shell currently, but that 's likely to change | 102 // doesn't seem to get triggered in VR Shell currently, but that 's likely to change |
98 // when we have omnibar navigation. | 103 // when we have omnibar navigation. |
99 } | 104 } |
100 }; | 105 }; |
101 } | 106 } |
102 | 107 |
103 /** | 108 /** |
104 * Should be called once the native library is loaded so that the native por tion of this | 109 * Should be called once the native library is loaded so that the native por tion of this |
105 * class can be initialized. | 110 * class can be initialized. |
106 */ | 111 */ |
107 public void onNativeLibraryReady() { | 112 public void onNativeLibraryReady() { |
108 if (mVrAvailable) { | 113 if (!mVrAvailable) return; |
109 mNativeVrShellDelegate = nativeInit(); | 114 mNativeVrShellDelegate = nativeInit(); |
110 } | |
111 } | 115 } |
112 | 116 |
113 @SuppressWarnings("unchecked") | 117 @SuppressWarnings("unchecked") |
114 private boolean maybeFindVrClasses() { | 118 private boolean maybeFindVrClasses() { |
115 try { | 119 try { |
116 mVrShellClass = (Class<? extends VrShell>) Class.forName( | 120 mVrShellClass = (Class<? extends VrShell>) Class.forName( |
117 "org.chromium.chrome.browser.vr_shell.VrShellImpl"); | 121 "org.chromium.chrome.browser.vr_shell.VrShellImpl"); |
118 mNonPresentingGvrContextClass = | 122 mNonPresentingGvrContextClass = |
119 (Class<? extends NonPresentingGvrContext>) Class.forName( | 123 (Class<? extends NonPresentingGvrContext>) Class.forName( |
120 "org.chromium.chrome.browser.vr_shell.NonPresentingG vrContextImpl"); | 124 "org.chromium.chrome.browser.vr_shell.NonPresentingG vrContextImpl"); |
121 mVrDaydreamApiClass = (Class<? extends VrDaydreamApi>) Class.forName ( | 125 mVrDaydreamApiClass = (Class<? extends VrDaydreamApi>) Class.forName ( |
122 "org.chromium.chrome.browser.vr_shell.VrDaydreamApiImpl"); | 126 "org.chromium.chrome.browser.vr_shell.VrDaydreamApiImpl"); |
123 mVrCoreVersionCheckerClass = (Class<? extends VrCoreVersionChecker>) Class.forName( | 127 mVrCoreVersionCheckerClass = (Class<? extends VrCoreVersionChecker>) Class.forName( |
124 "org.chromium.chrome.browser.vr_shell.VrCoreVersionCheckerIm pl"); | 128 "org.chromium.chrome.browser.vr_shell.VrCoreVersionCheckerIm pl"); |
125 return true; | 129 return true; |
126 } catch (ClassNotFoundException e) { | 130 } catch (ClassNotFoundException e) { |
127 mVrShellClass = null; | 131 mVrShellClass = null; |
128 mNonPresentingGvrContextClass = null; | 132 mNonPresentingGvrContextClass = null; |
129 mVrDaydreamApiClass = null; | 133 mVrDaydreamApiClass = null; |
130 mVrCoreVersionCheckerClass = null; | 134 mVrCoreVersionCheckerClass = null; |
131 return false; | 135 return false; |
132 } | 136 } |
133 } | 137 } |
134 | 138 |
135 /** | 139 /** |
136 * Handle a VR intent, entering VR in the process. | 140 * Handle a VR intent, entering VR in the process. |
137 */ | 141 */ |
138 public boolean enterVRFromIntent(Intent intent) { | 142 public void enterVRFromIntent(Intent intent) { |
143 if (!mVrAvailable) return; | |
139 assert isVrIntent(intent); | 144 assert isVrIntent(intent); |
140 int transitionType = intent.getIntExtra(DAYDREAM_DON_TYPE, DAYDREAM_DON_ TYPE_VR_SHELL); | 145 if (enterVR()) { |
141 if (!isVrShellEnabled()) { | 146 nativeSetPresentResult(mNativeVrShellDelegate, true); |
142 assert transitionType != DAYDREAM_DON_TYPE_VR_SHELL; | 147 if (mRequestedWebVR) mVrShell.setWebVrModeEnabled(true); |
148 } else { | |
149 nativeSetPresentResult(mNativeVrShellDelegate, false); | |
150 mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent()); | |
143 } | 151 } |
144 | 152 |
145 boolean inWebVR = transitionType == DAYDREAM_DON_TYPE_WEBVR | 153 mRequestedWebVR = false; |
146 || (transitionType == DAYDREAM_DON_TYPE_AUTO | 154 } |
147 && (!isVrShellEnabled() || mRequestedWebVR)); | |
148 Tab tab = mActivity.getActivityTab(); | |
149 if (!canEnterVR(inWebVR, tab)) return false; | |
150 | 155 |
151 // TODO(mthiesse): We should handle switching between webVR and VR Shell mode through | 156 private boolean enterVR() { |
152 // intents. | |
153 if (mInVr) return true; | 157 if (mInVr) return true; |
154 | |
155 mVrDaydreamApi.setVrModeEnabled(true); | 158 mVrDaydreamApi.setVrModeEnabled(true); |
156 | 159 |
157 mTab = tab; | 160 Tab tab = mActivity.getActivityTab(); |
158 mTab.addObserver(mTabObserver); | 161 if (!canEnterVR(tab)) return false; |
159 | 162 |
160 mRestoreOrientation = mActivity.getRequestedOrientation(); | 163 mRestoreOrientation = mActivity.getRequestedOrientation(); |
161 mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSC APE); | 164 mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSC APE); |
162 if (!createVrShell()) { | 165 if (!createVrShell()) { |
163 mActivity.setRequestedOrientation(mRestoreOrientation); | 166 mActivity.setRequestedOrientation(mRestoreOrientation); |
164 return false; | 167 return false; |
165 } | 168 } |
169 mInVr = true; | |
170 mTab = tab; | |
171 mTab.addObserver(mTabObserver); | |
166 addVrViews(); | 172 addVrViews(); |
167 setupVrModeWindowFlags(); | 173 setupVrModeWindowFlags(); |
168 mVrShell.initializeNative(mTab, this); | 174 mVrShell.initializeNative(mTab, this); |
169 if (inWebVR) mVrShell.setWebVrModeEnabled(true); | |
170 // onResume needs to be called on GvrLayout after initialization to make sure DON flow work | 175 // onResume needs to be called on GvrLayout after initialization to make sure DON flow work |
171 // properly. | 176 // properly. |
172 mVrShell.resume(); | 177 mVrShell.resume(); |
173 mInVr = true; | |
174 mTab.updateFullscreenEnabledState(); | 178 mTab.updateFullscreenEnabledState(); |
175 return true; | 179 return true; |
176 } | 180 } |
177 | 181 |
178 private boolean canEnterVR(boolean inWebVR, Tab tab) { | 182 private boolean canEnterVR(Tab tab) { |
179 if (!LibraryLoader.isInitialized()) { | 183 if (!LibraryLoader.isInitialized()) { |
180 return false; | 184 return false; |
181 } | 185 } |
182 // If vr isn't in the build, or we haven't initialized yet, or vr shell is not enabled and | 186 // If vr isn't in the build, or we haven't initialized yet, or vr shell is not enabled and |
183 // this is not a web vr request, then return immediately. | 187 // this is not a web vr request, then return immediately. |
184 if (!mVrAvailable || mNativeVrShellDelegate == 0 || (!isVrShellEnabled() && !inWebVR)) { | 188 if (!mVrAvailable || mNativeVrShellDelegate == 0 |
189 || (!isVrShellEnabled() && !mRequestedWebVR)) { | |
185 return false; | 190 return false; |
186 } | 191 } |
187 // TODO(mthiesse): When we have VR UI for opening new tabs, etc., allow VR Shell to be | 192 // TODO(mthiesse): When we have VR UI for opening new tabs, etc., allow VR Shell to be |
188 // entered without any current tabs. | 193 // entered without any current tabs. |
189 if (tab == null || tab.getContentViewCore() == null) { | 194 if (tab == null || tab.getContentViewCore() == null) { |
190 return false; | 195 return false; |
191 } | 196 } |
192 | 197 |
193 // For now we don't handle native pages. crbug.com/661609 | 198 // For now we don't handle native pages. crbug.com/661609 |
194 if (tab.getNativePage() != null || tab.isShowingSadTab()) { | 199 if (tab.getNativePage() != null || tab.isShowingSadTab()) { |
195 return false; | 200 return false; |
196 } | 201 } |
197 return true; | 202 return true; |
198 } | 203 } |
199 | 204 |
205 @CalledByNative | |
206 private void presentRequested(boolean inWebVR) { | |
207 switch (enterVRIfNecessary()) { | |
208 case ENTER_VR_NOT_NECESSARY: | |
209 mVrShell.setWebVrModeEnabled(true); | |
210 nativeSetPresentResult(mNativeVrShellDelegate, true); | |
211 break; | |
212 case ENTER_VR_CANCELLED: | |
213 nativeSetPresentResult(mNativeVrShellDelegate, false); | |
214 break; | |
215 case ENTER_VR_REQUESTED: | |
216 // TODO(mthiesse): There's a GVR bug where they're not calling u s back with the | |
217 // intent we ask them to when we call DaydreamApi#launchInVr. As a temporary hack, | |
218 // remember locally that we want to enter webVR. | |
219 mRequestedWebVR = inWebVR; | |
220 break; | |
221 } | |
222 } | |
223 | |
200 /** | 224 /** |
201 * Enters VR Shell, displaying browser UI and tab contents in VR. | 225 * Enters VR Shell if necessary, displaying browser UI and tab contents in V R. |
202 * | |
203 * @param inWebVR If true should begin displaying WebVR content rather than the VrShell UI. | |
204 */ | 226 */ |
205 @CalledByNative | 227 public int enterVRIfNecessary() { |
206 public void enterVRIfNecessary(boolean inWebVR) { | 228 if (!mVrAvailable) return ENTER_VR_CANCELLED; |
207 if (mInVr) { | 229 if (mInVr) return ENTER_VR_NOT_NECESSARY; |
208 if (inWebVR) mVrShell.setWebVrModeEnabled(true); | 230 if (!canEnterVR(mActivity.getActivityTab())) return ENTER_VR_CANCELLED; |
209 return; | |
210 } | |
211 if (!canEnterVR(inWebVR, mActivity.getActivityTab())) return; | |
212 | 231 |
213 // TODO(mthiesse): There's a GVR bug where they're not calling us back w ith the intent we | 232 mVrDaydreamApi.launchInVr(getPendingEnterVRIntent()); |
214 // ask them to when we call DaydreamApi#launchInVr. As a temporary hack, remember locally | 233 return ENTER_VR_REQUESTED; |
215 // that we want to enter webVR. | |
216 mRequestedWebVR = inWebVR; | |
217 Intent intent = createDaydreamIntent( | |
218 inWebVR ? DAYDREAM_DON_TYPE_WEBVR : DAYDREAM_DON_TYPE_VR_SHELL); | |
219 | |
220 mVrDaydreamApi.launchInVr( | |
221 PendingIntent.getActivity(mActivity, 0, intent, PendingIntent.FL AG_ONE_SHOT)); | |
222 } | 234 } |
223 | 235 |
224 @CalledByNative | 236 @CalledByNative |
225 private boolean exitWebVR() { | 237 private boolean exitWebVR() { |
226 if (!mInVr) return false; | 238 if (!mInVr) return false; |
227 mVrShell.setWebVrModeEnabled(false); | 239 mVrShell.setWebVrModeEnabled(false); |
228 // TODO(bajones): Once VR Shell can be invoked outside of WebVR this | 240 // TODO(bajones): Once VR Shell can be invoked outside of WebVR this |
229 // should no longer exit the shell outright. Need a way to determine | 241 // should no longer exit the shell outright. Need a way to determine |
230 // how VrShell was created. | 242 // how VrShell was created. |
231 shutdownVR(true); | 243 shutdownVR(true); |
232 return true; | 244 return true; |
233 } | 245 } |
234 | 246 |
235 /** | 247 /** |
236 * Resumes VR Shell. | 248 * Resumes VR Shell. |
237 */ | 249 */ |
238 public void maybeResumeVR() { | 250 public void maybeResumeVR() { |
251 if (!mVrAvailable) return; | |
252 // TODO(mthiesse): Register the intent when on a page that supports WebV R, even if VrShell | |
253 // isn't enabled. | |
239 if (isVrShellEnabled()) { | 254 if (isVrShellEnabled()) { |
240 registerDaydreamIntent(); | 255 registerDaydreamIntent(); |
241 } | 256 } |
242 | 257 |
243 // TODO(bshe): Ideally, we do not need two gvr context exist at the same time. We can | 258 // TODO(bshe): Ideally, we do not need two gvr context exist at the same time. We can |
244 // probably shutdown non presenting gvr when presenting and create a new one after exit | 259 // probably shutdown non presenting gvr when presenting and create a new one after exit |
245 // presenting. See crbug.com/655242 | 260 // presenting. See crbug.com/655242 |
246 if (mNonPresentingGvrContext != null) { | 261 if (mNonPresentingGvrContext != null) { |
247 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites (); | 262 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites (); |
248 try { | 263 try { |
249 mNonPresentingGvrContext.resume(); | 264 mNonPresentingGvrContext.resume(); |
250 } catch (IllegalArgumentException e) { | 265 } catch (IllegalArgumentException e) { |
251 Log.e(TAG, "Unable to resume mNonPresentingGvrContext", e); | 266 Log.e(TAG, "Unable to resume mNonPresentingGvrContext", e); |
252 } finally { | 267 } finally { |
253 StrictMode.setThreadPolicy(oldPolicy); | 268 StrictMode.setThreadPolicy(oldPolicy); |
254 } | 269 } |
255 } | 270 } |
256 | 271 |
257 if (mInVr) { | 272 if (mInVr) { |
258 setupVrModeWindowFlags(); | 273 setupVrModeWindowFlags(); |
259 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites (); | 274 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites (); |
260 try { | 275 try { |
261 mVrShell.resume(); | 276 mVrShell.resume(); |
262 } catch (IllegalArgumentException e) { | 277 } catch (IllegalArgumentException e) { |
263 Log.e(TAG, "Unable to resume VrShell", e); | 278 Log.e(TAG, "Unable to resume VrShell", e); |
264 } finally { | 279 } finally { |
265 StrictMode.setThreadPolicy(oldPolicy); | 280 StrictMode.setThreadPolicy(oldPolicy); |
266 } | 281 } |
267 } else if (mLastVRExit + REENTER_VR_TIMEOUT_MS > SystemClock.uptimeMilli s()) { | 282 } else if (mLastVRExit + REENTER_VR_TIMEOUT_MS > SystemClock.uptimeMilli s()) { |
268 enterVRIfNecessary(mRequestedWebVR); | 283 enterVRIfNecessary(); |
269 } | 284 } |
270 } | 285 } |
271 | 286 |
272 /** | 287 /** |
273 * Pauses VR Shell. | 288 * Pauses VR Shell. |
274 */ | 289 */ |
275 public void maybePauseVR() { | 290 public void maybePauseVR() { |
276 if (isVrShellEnabled()) { | 291 if (!mVrAvailable) return; |
277 unregisterDaydreamIntent(); | 292 unregisterDaydreamIntent(); |
278 } | |
279 | 293 |
280 if (mNonPresentingGvrContext != null) { | 294 if (mNonPresentingGvrContext != null) { |
281 mNonPresentingGvrContext.pause(); | 295 mNonPresentingGvrContext.pause(); |
282 } | 296 } |
283 | 297 |
284 // TODO(mthiesse): When VR Shell lives in its own activity, and integrat es with Daydream | 298 // TODO(mthiesse): When VR Shell lives in its own activity, and integrat es with Daydream |
285 // home, pause instead of exiting VR here. For now, because VR Apps shou ldn't show up in the | 299 // home, pause instead of exiting VR here. For now, because VR Apps shou ldn't show up in the |
286 // non-VR recents, and we don't want ChromeTabbedActivity disappearing, exit VR. | 300 // non-VR recents, and we don't want ChromeTabbedActivity disappearing, exit VR. |
287 exitVRIfNecessary(false); | 301 exitVRIfNecessary(false); |
288 } | 302 } |
289 | 303 |
290 /** | 304 /** |
291 * Exits the current VR mode (WebVR or VRShell) | 305 * Exits the current VR mode (WebVR or VRShell) |
292 * @return Whether or not we exited VR. | 306 * @return Whether or not we exited VR. |
293 */ | 307 */ |
294 public boolean exitVRIfNecessary(boolean returnTo2D) { | 308 public boolean exitVRIfNecessary(boolean returnTo2D) { |
309 if (!mVrAvailable) return false; | |
295 if (!mInVr) return false; | 310 if (!mInVr) return false; |
296 // If WebVR is presenting instruct it to exit. | 311 // If WebVR is presenting instruct it to exit. |
297 nativeExitWebVRIfNecessary(mNativeVrShellDelegate); | 312 nativeExitWebVRIfNecessary(mNativeVrShellDelegate); |
298 shutdownVR(returnTo2D); | 313 shutdownVR(returnTo2D); |
299 return true; | 314 return true; |
300 } | 315 } |
301 | 316 |
302 public void onExitVRResult(int resultCode) { | 317 public void onExitVRResult(int resultCode) { |
318 assert mVrAvailable; | |
303 if (resultCode == Activity.RESULT_OK) { | 319 if (resultCode == Activity.RESULT_OK) { |
304 mVrDaydreamApi.setVrModeEnabled(false); | 320 mVrDaydreamApi.setVrModeEnabled(false); |
305 } else { | 321 } else { |
306 // For now, we don't handle re-entering VR when exit fails, so keep trying to exit. | 322 // For now, we don't handle re-entering VR when exit fails, so keep trying to exit. |
307 mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent()); | 323 mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent()); |
308 } | 324 } |
309 } | 325 } |
310 | 326 |
311 private Intent createDaydreamIntent(int transitionType) { | 327 private PendingIntent getPendingEnterVRIntent() { |
312 if (mVrDaydreamApi == null) return null; | 328 return PendingIntent.getActivity(mActivity, 0, mEnterVRIntent, PendingIn tent.FLAG_ONE_SHOT); |
313 // TODO(bshe): Ideally, this should go through ChromeLauncherActivity. T o avoid polluting | |
314 // metrics, use the VR Activity alias for now. | |
315 Intent intent = mVrDaydreamApi.createVrIntent( | |
316 new ComponentName(mActivity, VR_ACTIVITY_ALIAS)); | |
317 intent.putExtra(DAYDREAM_DON_TYPE, transitionType); | |
318 return intent; | |
319 } | 329 } |
320 | 330 |
321 /** | 331 /** |
322 * Registers the Intent to fire after phone inserted into a headset. | 332 * Registers the Intent to fire after phone inserted into a headset. |
323 */ | 333 */ |
324 private void registerDaydreamIntent() { | 334 private void registerDaydreamIntent() { |
325 if (mVrDaydreamApi == null) return; | 335 mVrDaydreamApi.registerDaydreamIntent(getPendingEnterVRIntent()); |
326 Intent intent = createDaydreamIntent(DAYDREAM_DON_TYPE_AUTO); | |
327 mVrDaydreamApi.registerDaydreamIntent( | |
328 PendingIntent.getActivity(mActivity, 0, intent, PendingIntent.FL AG_ONE_SHOT)); | |
329 } | 336 } |
330 | 337 |
331 /** | 338 /** |
332 * Unregisters the Intent which registered by this context if any. | 339 * Unregisters the Intent which registered by this context if any. |
333 */ | 340 */ |
334 private void unregisterDaydreamIntent() { | 341 private void unregisterDaydreamIntent() { |
335 if (mVrDaydreamApi != null) { | 342 mVrDaydreamApi.unregisterDaydreamIntent(); |
336 mVrDaydreamApi.unregisterDaydreamIntent(); | |
337 } | |
338 } | 343 } |
339 | 344 |
340 @CalledByNative | 345 @CalledByNative |
341 private long createNonPresentingNativeContext() { | 346 private long createNonPresentingNativeContext() { |
342 if (!mVrAvailable) return 0; | 347 if (!mVrAvailable) return 0; |
343 | 348 |
344 try { | 349 try { |
345 Constructor<?> nonPresentingGvrContextConstructor = | 350 Constructor<?> nonPresentingGvrContextConstructor = |
346 mNonPresentingGvrContextClass.getConstructor(Activity.class) ; | 351 mNonPresentingGvrContextClass.getConstructor(Activity.class) ; |
347 mNonPresentingGvrContext = | 352 mNonPresentingGvrContext = |
(...skipping 11 matching lines...) Expand all Loading... | |
359 private void shutdownNonPresentingNativeContext() { | 364 private void shutdownNonPresentingNativeContext() { |
360 mNonPresentingGvrContext.shutdown(); | 365 mNonPresentingGvrContext.shutdown(); |
361 mNonPresentingGvrContext = null; | 366 mNonPresentingGvrContext = null; |
362 } | 367 } |
363 | 368 |
364 /** | 369 /** |
365 * Exits VR Shell, performing all necessary cleanup. | 370 * Exits VR Shell, performing all necessary cleanup. |
366 */ | 371 */ |
367 private void shutdownVR(boolean returnTo2D) { | 372 private void shutdownVR(boolean returnTo2D) { |
368 if (!mInVr) return; | 373 if (!mInVr) return; |
374 mRequestedWebVR = false; | |
369 if (returnTo2D) { | 375 if (returnTo2D) { |
370 mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent()); | 376 mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent()); |
371 } else { | 377 } else { |
372 mVrDaydreamApi.setVrModeEnabled(false); | 378 mVrDaydreamApi.setVrModeEnabled(false); |
373 mLastVRExit = SystemClock.uptimeMillis(); | 379 mLastVRExit = SystemClock.uptimeMillis(); |
374 } | 380 } |
375 mActivity.setRequestedOrientation(mRestoreOrientation); | 381 mActivity.setRequestedOrientation(mRestoreOrientation); |
376 mVrShell.pause(); | 382 mVrShell.pause(); |
377 removeVrViews(); | 383 removeVrViews(); |
378 clearVrModeWindowFlags(); | 384 clearVrModeWindowFlags(); |
(...skipping 13 matching lines...) Expand all Loading... | |
392 return false; | 398 return false; |
393 } | 399 } |
394 | 400 |
395 try { | 401 try { |
396 Constructor<?> mVrCoreVersionCheckerConstructor = | 402 Constructor<?> mVrCoreVersionCheckerConstructor = |
397 mVrCoreVersionCheckerClass.getConstructor(); | 403 mVrCoreVersionCheckerClass.getConstructor(); |
398 mVrCoreVersionChecker = | 404 mVrCoreVersionChecker = |
399 (VrCoreVersionChecker) mVrCoreVersionCheckerConstructor.newI nstance(); | 405 (VrCoreVersionChecker) mVrCoreVersionCheckerConstructor.newI nstance(); |
400 } catch (InstantiationException | IllegalAccessException | IllegalArgume ntException | 406 } catch (InstantiationException | IllegalAccessException | IllegalArgume ntException |
401 | InvocationTargetException | NoSuchMethodException e) { | 407 | InvocationTargetException | NoSuchMethodException e) { |
402 Log.e(TAG, "Unable to instantiate VrCoreVersionChecker", e); | 408 Log.d(TAG, "Unable to instantiate VrCoreVersionChecker", e); |
403 return false; | 409 return false; |
404 } | 410 } |
405 return mVrCoreVersionChecker.isVrCoreCompatible(); | 411 return mVrCoreVersionChecker.isVrCoreCompatible(); |
406 } | 412 } |
407 | 413 |
408 private boolean createVrDaydreamApi() { | 414 private boolean createVrDaydreamApi() { |
409 if (!mVrAvailable) return false; | |
410 | |
411 try { | 415 try { |
412 Constructor<?> vrPrivateApiConstructor = | 416 Constructor<?> vrPrivateApiConstructor = |
413 mVrDaydreamApiClass.getConstructor(Activity.class); | 417 mVrDaydreamApiClass.getConstructor(Activity.class); |
414 mVrDaydreamApi = (VrDaydreamApi) vrPrivateApiConstructor.newInstance (mActivity); | 418 mVrDaydreamApi = (VrDaydreamApi) vrPrivateApiConstructor.newInstance (mActivity); |
415 } catch (InstantiationException | IllegalAccessException | IllegalArgume ntException | 419 } catch (InstantiationException | IllegalAccessException | IllegalArgume ntException |
416 | InvocationTargetException | NoSuchMethodException e) { | 420 | InvocationTargetException | NoSuchMethodException | SecurityEx ception e) { |
417 Log.e(TAG, "Unable to instantiate VrDaydreamApi", e); | 421 Log.d(TAG, "Unable to instantiate VrDaydreamApi", e); |
418 return false; | 422 return false; |
419 } | 423 } |
420 return true; | 424 return true; |
421 } | 425 } |
422 | 426 |
423 private boolean createVrShell() { | 427 private boolean createVrShell() { |
424 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); | 428 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); |
425 StrictMode.allowThreadDiskWrites(); | 429 StrictMode.allowThreadDiskWrites(); |
426 try { | 430 try { |
427 Constructor<?> vrShellConstructor = mVrShellClass.getConstructor(Act ivity.class); | 431 Constructor<?> vrShellConstructor = mVrShellClass.getConstructor(Act ivity.class); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
506 if (mVrShellEnabled == null) { | 510 if (mVrShellEnabled == null) { |
507 if (!LibraryLoader.isInitialized()) { | 511 if (!LibraryLoader.isInitialized()) { |
508 return false; | 512 return false; |
509 } | 513 } |
510 mVrShellEnabled = ChromeFeatureList.isEnabled(ChromeFeatureList.VR_S HELL); | 514 mVrShellEnabled = ChromeFeatureList.isEnabled(ChromeFeatureList.VR_S HELL); |
511 } | 515 } |
512 return mVrShellEnabled; | 516 return mVrShellEnabled; |
513 } | 517 } |
514 | 518 |
515 /** | 519 /** |
516 * @return Whether or not VR Shell is currently enabled. | |
517 */ | |
518 public boolean isVrInitialized() { | |
519 return mVrDaydreamApi != null; | |
520 } | |
521 | |
522 /** | |
523 * @return Pointer to the native VrShellDelegate object. | 520 * @return Pointer to the native VrShellDelegate object. |
524 */ | 521 */ |
525 @CalledByNative | 522 @CalledByNative |
526 private long getNativePointer() { | 523 private long getNativePointer() { |
527 return mNativeVrShellDelegate; | 524 return mNativeVrShellDelegate; |
528 } | 525 } |
529 | 526 |
530 private native long nativeInit(); | 527 private native long nativeInit(); |
531 private native void nativeExitWebVRIfNecessary(long nativeVrShellDelegate); | 528 private native void nativeExitWebVRIfNecessary(long nativeVrShellDelegate); |
529 private native void nativeSetPresentResult(long nativeVrShellDelegate, boole an result); | |
532 } | 530 } |
OLD | NEW |