Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java

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

Powered by Google App Engine
This is Rietveld 408576698