// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.vr;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.StrictMode;
import android.provider.Settings;
import android.support.annotation.IntDef;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.FrameLayout;

import com.google.vr.ndk.base.AndroidCompat;
import com.google.vr.ndk.base.DaydreamApi;
import com.google.vr.ndk.base.GvrUiLayout;

import org.chromium.base.ActivityState;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.CollectionUtil;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import org.chromium.base.PackageUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.base.task.AsyncTask;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ApplicationLifetime;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.customtabs.CustomTabActivity;
import org.chromium.chrome.browser.help.HelpAndFeedback;
import org.chromium.chrome.browser.infobar.InfoBarIdentifier;
import org.chromium.chrome.browser.infobar.SimpleConfirmInfoBarBuilder;
import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.webapps.WebappActivity;
import org.chromium.content_public.browser.ScreenOrientationDelegate;
import org.chromium.content_public.browser.ScreenOrientationProvider;
import org.chromium.ui.display.DisplayAndroidManager;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.RejectedExecutionException;

/**
 * Manages interactions with the VR Shell.
 */
@JNINamespace("vr")
public class VrShellDelegate
        implements View.OnSystemUiVisibilityChangeListener, ScreenOrientationDelegate {
    private static final String TAG = "VrShellDelegate";

    // Pseudo-random number to avoid request id collisions. Result codes must fit in lower 16 bits
    // when used with startActivityForResult...
    /* package */ static final int EXIT_VR_RESULT = 7212;
    private static final int VR_SERVICES_UPDATE_RESULT = 7213;
    private static final int GVR_KEYBOARD_UPDATE_RESULT = 7214;

    @IntDef({EnterVRResult.NOT_NECESSARY, EnterVRResult.CANCELLED, EnterVRResult.REQUESTED,
            EnterVRResult.SUCCEEDED})
    @Retention(RetentionPolicy.SOURCE)
    private @interface EnterVRResult {
        int NOT_NECESSARY = 0;
        int CANCELLED = 1;
        int REQUESTED = 2;
        int SUCCEEDED = 3;
    }

    private static final String VR_ENTRY_RESULT_ACTION =
            "org.chromium.chrome.browser.vr.VrEntryResult";

    private static final long REENTER_VR_TIMEOUT_MS = 1000;

    private static final String FEEDBACK_REPORT_TYPE = "USER_INITIATED_FEEDBACK_REPORT_VR";

    private static final String VR_CORE_MARKET_URI =
            "market://details?id=" + VrCoreVersionChecker.VR_CORE_PACKAGE_ID;

    private static final String GVR_KEYBOARD_PACKAGE_ID = "com.google.android.vr.inputmethod";
    private static final String GVR_KEYBOARD_MARKET_URI =
            "market://details?id=" + GVR_KEYBOARD_PACKAGE_ID;

    private static final String SAMSUNG_GALAXY_PREFIX = "SM-";
    private static final Set<String> SAMSUNG_GALAXY_8_MODELS =
            Collections.unmodifiableSet(CollectionUtil.newHashSet("G950", "N950", "G955", "G892"));

    private static final Set<String> SAMSUNG_GALAXY_8_ALT_MODELS = Collections.unmodifiableSet(
            CollectionUtil.newHashSet("SC-02J", "SCV36", "SC-03J", "SCV35", "SC-01K", "SCV37"));

    // This value is intentionally probably overkill. This is the time we need to wait from when
    // Chrome is resumed, to when Chrome actually renders a black frame, so that we can cancel the
    // stay_hidden animation and not see a white monoscopic frame in-headset. 150ms is definitely
    // too short, 250ms is sometimes too short for debug builds. 500ms should hopefully be safe even
    // under fairly exceptional conditions, and won't delay entering VR a noticeable amount given
    // how slow it already is.
    private static final int WINDOW_FADE_ANIMATION_DURATION_MS = 500;

    /** ID for SavedInstanceState Bundle for whether Chrome was in VR when killed. */
    private static final String IN_VR = "in_vr";

    private static VrShellDelegate sInstance;
    private static VrBroadcastReceiver sVrBroadcastReceiver;
    private static VrLifecycleObserver sVrLifecycleObserver;
    private static VrDaydreamApi sVrDaydreamApi;
    private static VrCoreVersionChecker sVrCoreVersionChecker;
    private static Set<Activity> sVrModeEnabledActivitys = new HashSet<>();
    private static boolean sRegisteredDaydreamHook;
    private static boolean sRegisteredVrAssetsComponent;
    private static @VrSupportLevel Integer sVrSupportLevel;
    private static boolean sTestVrShellDelegateOnStartup;

    private ChromeActivity mActivity;

    private int mCachedVrCorePackageVersion;
    private int mCachedGvrKeyboardPackageVersion;

    // How often to prompt the user to enter VR feedback.
    private int mFeedbackFrequency;

    private VrShell mVrShell;
    private Boolean mIsDaydreamCurrentViewer;
    private boolean mProbablyInDon;
    private boolean mInVr;
    private boolean mNeedsAnimationCancel;
    private boolean mCancellingEntryAnimation;

    // Whether or not the VR Device ON flow succeeded. If this is true it means the user has a VR
    // headset on, but we haven't switched into VR mode yet.
    // See further documentation here: https://developers.google.com/vr/daydream/guides/vr-entry
    private boolean mDonSucceeded;
    private boolean mShowingDaydreamDoff;
    private boolean mShowingExitVrPrompt;
    private boolean mDoffOptional;
    // Listener to be called once we exited VR due to to an unsupported mode, e.g. the user clicked
    // the URL bar security icon.
    private OnExitVrRequestListener mOnExitVrRequestListener;
    private Runnable mPendingExitVrRequest;
    private Boolean mShowVrServicesUpdatePrompt;
    private boolean mShowingDoffForGvrUpdate;
    private boolean mExitedDueToUnsupportedMode;
    private boolean mPaused;
    private boolean mVisible;
    private boolean mRestoreSystemUiVisibility;
    private Integer mRestoreOrientation;
    private boolean mRequestedWebVr;
    private boolean mListeningForWebVrActivate;
    private boolean mMaybeActivateAfterHeadsetInsertion;
    private Handler mClearMaybeActivateHandler = new Handler();
    private boolean mActivateFromHeadsetInsertion;
    private boolean mStartedFromVrIntent;

    private boolean mInternalIntentUsedToStartVr;

    // Set to true if performed VR browsing at least once. That is, this was not simply a WebVr
    // presentation experience.
    private boolean mVrBrowserUsed;

    private int mExpectedDensityChange;

    // Gets run when the user exits VR mode by clicking the 'x' button or system UI back button.
    private Runnable mCloseButtonListener;

    // Gets run when the user exits VR mode by clicking the Gear button.
    private Runnable mSettingsButtonListener;

    @VisibleForTesting
    protected boolean mTestWorkaroundDontCancelVrEntryOnResume;

    private long mNativeVrShellDelegate;

    /* package */ final static class VrUnsupportedException extends RuntimeException {}

    private static final class VrLifecycleObserver
            implements ApplicationStatus.ActivityStateListener {
        @Override
        public void onActivityStateChange(Activity activity, int newState) {
            switch (newState) {
                case ActivityState.DESTROYED:
                    if (sVrBroadcastReceiver != null
                            && sVrBroadcastReceiver.targetActivity().get() == activity) {
                        sVrBroadcastReceiver.unregister();
                        sVrBroadcastReceiver = null;
                    }
                    sVrModeEnabledActivitys.remove(activity);
                    break;
                default:
                    break;
            }
            if (sInstance != null) sInstance.onActivityStateChange(activity, newState);
        }
    }

    private static final class VrBroadcastReceiver extends BroadcastReceiver {
        private final WeakReference<ChromeActivity> mTargetActivity;

        public VrBroadcastReceiver(ChromeActivity activity) {
            ensureLifecycleObserverInitialized();
            mTargetActivity = new WeakReference<ChromeActivity>(activity);
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            ChromeActivity activity = mTargetActivity.get();
            if (activity == null) return;
            getInstance(activity);
            assert sInstance != null;
            if (sInstance == null) return;
            sInstance.onBroadcastReceived();

            // Note that even though we are definitely entering VR here, we don't want to set
            // the window mode yet, as setting the window mode while we're in the background can
            // racily lead to that window mode change essentially being ignored, with future
            // attempts to set the same window mode also being ignored.

            sInstance.mDonSucceeded = true;
            sInstance.mProbablyInDon = false;
            setVrModeEnabled(sInstance.mActivity, true);
            if (VrDelegate.DEBUG_LOGS) Log.i(TAG, "VrBroadcastReceiver onReceive");

            if (!sInstance.mRequestedWebVr && !sInstance.mStartedFromVrIntent) {
                // If we didn't request WebVR then we're not coming from a request present call.
                // If we didn't set mStartedFromVrIntent this isn't an intent from another app.
                // Therefore we can assume this was triggered by NFC.
                sInstance.nativeRecordVrStartAction(
                        sInstance.mNativeVrShellDelegate, VrStartAction.HEADSET_ACTIVATION);
            }

            // We add a black overlay view so that we can show black while the VR UI is loading.
            if (!sInstance.mInVr)
                VrModuleProvider.getDelegate().addBlackOverlayViewForActivity(sInstance.mActivity);

            // For headset insertion handling it should be impossible in practice to receive this
            // broadcast after being resumed. However, with VR entry flows skipped, these events
            // can happen out of order. See https://crbug.com/762724.
            sInstance.mActivateFromHeadsetInsertion = sInstance.mMaybeActivateAfterHeadsetInsertion;

            if (sInstance.mPaused) {
                if (activity instanceof ChromeTabbedActivity) {
                    // We can special case singleInstance activities like CTA to avoid having to use
                    // moveTaskToFront. Using moveTaskToFront prevents us from disabling window
                    // animations, and causes the system UI to show up during the preview window and
                    // window animations.
                    Intent launchIntent = new Intent(activity, activity.getClass());
                    launchIntent = VrModuleProvider.getIntentDelegate().setupVrIntent(launchIntent);
                    sInstance.mInternalIntentUsedToStartVr = true;
                    sInstance.setExpectingIntent(true);
                    getVrDaydreamApi().launchInVr(PendingIntent.getActivity(
                            activity, 0, launchIntent, PendingIntent.FLAG_UPDATE_CURRENT));
                } else {
                    // We start the Activity with a custom animation that keeps it hidden while
                    // starting up to avoid Android showing stale 2D screenshots when the user is in
                    // their VR headset. The animation lasts up to 10 seconds, but is cancelled when
                    // we're resumed as at that time we'll be showing the black overlay added above.
                    int animation = !sInstance.mInVr && VrDelegate.USE_HIDE_ANIMATION
                            ? R.anim.stay_hidden
                            : 0;
                    sInstance.mNeedsAnimationCancel = animation != 0;
                    Bundle options =
                            ActivityOptions.makeCustomAnimation(activity, animation, 0).toBundle();
                    ((ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE))
                            .moveTaskToFront(activity.getTaskId(), 0, options);
                }
            } else {
                // If a WebVR app calls requestPresent in response to the displayactivate event
                // after the DON flow completes, the DON flow is skipped, meaning our app won't be
                // paused when daydream fires our BroadcastReceiver, so onResume won't be called.
                sInstance.handleDonFlowSuccess();
            }
        }

        /**
         * Unregisters this {@link BroadcastReceiver} from the activity it's registered to.
         */
        public void unregister() {
            ChromeActivity activity = mTargetActivity.get();
            if (activity == null) return;
            try {
                activity.unregisterReceiver(VrBroadcastReceiver.this);
            } catch (IllegalArgumentException e) {
                // Ignore this. This means our receiver was already unregistered somehow.
            }
        }

        WeakReference<ChromeActivity> targetActivity() {
            return mTargetActivity;
        }
    }

    /**
     * Immediately exits VR. If the user is in headset, they will see monoscopic UI while in the
     * headset, so use with caution.
     */
    public static void forceExitVrImmediately() {
        if (sInstance == null) return;
        sInstance.shutdownVr(true, true);
    }

    /**
     * See {@link Activity#onActivityResult}.
     */
    public static boolean onActivityResultWithNative(int requestCode, int resultCode) {
        // Handles the result of the exit VR flow (DOFF).
        if (requestCode == EXIT_VR_RESULT) {
            if (sInstance != null) sInstance.onExitVrResult(resultCode == Activity.RESULT_OK);
            return true;
        }
        // Handles the result of requesting to update VR services.
        if (requestCode == VR_SERVICES_UPDATE_RESULT) {
            if (sInstance != null) sInstance.onVrServicesMaybeUpdated();
            return true;
        }
        // Handles the result of requesting to update GVR Keyboard.
        if (requestCode == GVR_KEYBOARD_UPDATE_RESULT) {
            if (sInstance != null) sInstance.onGvrKeyboardMaybeUpdated();
            return true;
        }
        return false;
    }

    /**
     * Called when the native library is first available.
     */
    public static void onNativeLibraryAvailable() {
        VrModuleProvider.registerJni();
        nativeOnLibraryAvailable();
    }

    /**
     * Whether or not we are currently in VR.
     */
    public static boolean isInVr() {
        if (sInstance == null) return false;
        return sInstance.mInVr;
    }

    /**
     * @return Whether 2D intents can safely be launched without showing non-VR UI to users in VR
     *         headsets.
     */
    public static boolean canLaunch2DIntents() {
        if (!isInVr()) return true;
        return sInstance.canLaunch2DIntentsInternal();
    }

    /**
     * See {@link ChromeActivity#handleBackPressed}
     * Only handles the back press while in VR.
     */
    public static boolean onBackPressed() {
        if (sInstance == null) return false;
        return sInstance.onBackPressedInternal();
    }

    /**
     * Enters VR on the current tab if possible.
     *
     * @return Whether VR entry succeeded (or is in progress).
     */
    public static boolean enterVrIfNecessary() {
        boolean created_delegate = sInstance == null;
        VrShellDelegate instance = getInstance();
        if (instance == null) return false;
        int result = instance.enterVrInternal();
        if (result == EnterVRResult.CANCELLED && created_delegate) instance.destroy();
        return result != EnterVRResult.CANCELLED;
    }

    /**
     * If VR Shell is enabled, and the activity is supported, register with the Daydream
     * platform that this app would like to be launched in VR when the device enters VR.
     */
    public static void maybeRegisterVrEntryHook(final ChromeActivity activity) {
        // Daydream is not supported on pre-N devices.
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return;
        if (sInstance != null) return; // Will be handled in onResume.
        if (!VrModuleProvider.getDelegate().activitySupportsVrBrowsing(activity)
                && sRegisteredVrAssetsComponent)
            return;

        // Short-circuit the asnyc task if we've already queried support level previously. Creating
        // the async task takes ~1ms on my Android Go device.
        if (sVrSupportLevel != null && sVrSupportLevel != VrSupportLevel.VR_DAYDREAM) return;

        try {
            // Reading VR support level and version can be slow, so do it asynchronously.
            new AsyncTask<Integer>() {
                @Override
                protected Integer doInBackground() {
                    return getVrSupportLevel();
                }

                @Override
                protected void onPostExecute(Integer vrSupportLevel) {
                    if (vrSupportLevel != VrSupportLevel.VR_DAYDREAM) return;

                    if (!sRegisteredVrAssetsComponent) {
                        registerVrAssetsComponentIfDaydreamUser(isDaydreamCurrentViewer());
                    }

                    // Registering the daydream intent has to be done on the UI thread. Note that
                    // this call is slow (~10ms at time of writing).
                    if (isVrBrowsingEnabled(activity, vrSupportLevel)
                            && ApplicationStatus.getStateForActivity(activity)
                                    == ActivityState.RESUMED) {
                        registerDaydreamIntent(activity);
                    }
                }
            }
                    .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        } catch (RejectedExecutionException ex) {
            // This isn't critical work, so it's okay to fail silently. If the user does try to
            // enter VR the asset component may not be available, and headset insertion will go to
            // Daydream rather than Chrome.
        }
    }

    /**
     * When the app is pausing we need to unregister with the Daydream platform to prevent this app
     * from being launched from the background when the device enters VR.
     */
    public static void maybeUnregisterVrEntryHook() {
        // Daydream is not supported on pre-N devices.
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return;
        if (sInstance != null) return; // Will be handled in onPause.
        if (!sRegisteredDaydreamHook) return;
        unregisterDaydreamIntent();
    }

    public static void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
        if (isInMultiWindowMode && isInVr()) {
            sInstance.shutdownVr(true /* disableVrMode */, true /* stayingInChrome */);
        }
    }

    public static void requestToExitVrForSearchEnginePromoDialog(
            OnExitVrRequestListener listener, Activity activity) {
        // When call site requests to exit VR, depend on the timing, Chrome may not in VR yet
        // (Chrome only enter VR after onNewIntentWithNative is called in the cold start case).
        // While not in VR, calling requestToExitVr would immediately notify listener that exit VR
        // succeed (without showing DOFF screen). If call site decide to show 2D UI when exit VR
        // succeeded, it leads to case that 2D UI is showing on top of VR when Chrome eventually
        // enters VR. To prevent this from happening, we set mPendingExitVrRequest which should be
        // executed at runPendingExitVrTask. runPendingExitVrTask is called after it is safe to
        // request exit VR.
        if (isInVr()) {
            sInstance.requestToExitVrInternal(
                    listener, UiUnsupportedMode.SEARCH_ENGINE_PROMO, false);
        } else {
            // Making sure that we response to this request as it is very important that search
            // engine promo dialog isn't ignored due to VR.
            assert VrModuleProvider.getIntentDelegate().isVrIntent(activity.getIntent());
            VrShellDelegate instance = getInstance();
            if (instance == null) {
                listener.onDenied();
                return;
            }
            sInstance.mPendingExitVrRequest = () -> {
                VrShellDelegate.requestToExitVr(listener, UiUnsupportedMode.SEARCH_ENGINE_PROMO);
            };
        }
    }

    public static void requestToExitVr(OnExitVrRequestListener listener) {
        requestToExitVr(listener, UiUnsupportedMode.GENERIC_UNSUPPORTED_FEATURE);
    }

    public static void requestToExitVr(
            OnExitVrRequestListener listener, @UiUnsupportedMode int reason) {
        // If we're not in VR, just say that we've successfully exited VR.
        if (sInstance == null || !sInstance.mInVr) {
            listener.onSucceeded();
            return;
        }
        sInstance.requestToExitVrInternal(listener, reason, !supports2dInVr());
    }

    public static void requestToExitVrAndRunOnSuccess(Runnable onSuccess) {
        requestToExitVrAndRunOnSuccess(onSuccess, UiUnsupportedMode.GENERIC_UNSUPPORTED_FEATURE);
    }

    public static void requestToExitVrAndRunOnSuccess(
            Runnable onSuccess, @UiUnsupportedMode int reason) {
        requestToExitVr(new OnExitVrRequestListener() {
            @Override
            public void onSucceeded() {
                onSuccess.run();
            }

            @Override
            public void onDenied() {}
        }, reason);
    }

    /**
     * Called when the {@link ChromeActivity} becomes visible.
     */
    public static void onActivityShown(ChromeActivity activity) {
        if (sInstance != null && sInstance.mActivity == activity) sInstance.onActivityShown();
    }

    /**
     * Called when the {@link ChromeActivity} is hidden.
     */
    public static void onActivityHidden(ChromeActivity activity) {
        if (sInstance != null && sInstance.mActivity == activity) sInstance.onActivityHidden();
    }

    /**
     * @return Whether VrShellDelegate handled the density change. If the density change is
     * unhandled, the Activity should be recreated in order to handle the change.
     */
    public static boolean onDensityChanged(int oldDpi, int newDpi) {
        if (VrDelegate.DEBUG_LOGS) Log.i(TAG, "onDensityChanged [%d]->[%d] ", oldDpi, newDpi);
        if (sInstance == null) return false;
        // If density changed while in VR, we expect a second density change to restore the density
        // to what it previously was when we exit VR. We shouldn't have to recreate the activity as
        // all non-VR UI is still using the old density.
        if (sInstance.mExpectedDensityChange != 0) {
            assert !sInstance.mInVr && !sInstance.mDonSucceeded;
            int expectedDensity = sInstance.mExpectedDensityChange;
            sInstance.mExpectedDensityChange = 0;
            return (newDpi == expectedDensity);
        }
        if (sInstance.mInVr || sInstance.mDonSucceeded) {
            sInstance.mExpectedDensityChange = oldDpi;
            return true;
        }
        return false;
    }

    /**
     * @param topContentOffset The top content offset (usually applied by the omnibox).
     */
    public static void rawTopContentOffsetChanged(float topContentOffset) {
        assert isInVr();
        sInstance.mVrShell.rawTopContentOffsetChanged(topContentOffset);
    }

    /**
     * This is called every time ChromeActivity gets a new intent.
     */
    public static void onNewIntentWithNative(ChromeActivity activity, Intent intent) {
        if (activity.isFinishing()) return;
        if (!VrModuleProvider.getIntentDelegate().isLaunchingIntoVr(activity, intent)) return;

        VrShellDelegate instance = getInstance(activity);
        if (instance == null) return;
        instance.onNewVrIntent();
    }

    /**
     * This is called when ChromeTabbedActivity gets a new intent before native is initialized.
     */
    public static void maybeHandleVrIntentPreNative(ChromeActivity activity, Intent intent) {
        boolean launchingIntoVr =
                VrModuleProvider.getIntentDelegate().isLaunchingIntoVr(activity, intent);

        if (!launchingIntoVr) {
            // We trust that if an intent is targeted for 2D, that Chrome should switch to 2D
            // regardless of whether the user is in headset.
            if (VrShellDelegate.isInVr()) VrShellDelegate.forceExitVrImmediately();
            return;
        }

        if (VrModuleProvider.getDelegate().bootsToVr() && launchingIntoVr) {
            if (VrModuleProvider.getDelegate().relaunchOnMainDisplayIfNecessary(activity, intent)) {
                return;
            }
        }

        if (sInstance != null && !sInstance.mInternalIntentUsedToStartVr) {
            sInstance.swapHostActivity(activity, false /* disableVrMode */);
            // If the user has launched Chrome from the launcher, rather than resuming from the
            // dashboard, we don't want to launch into presentation.
            sInstance.exitWebVRAndClearState();
        }

        if (sInstance != null) sInstance.setExpectingIntent(false);

        if (VrDelegate.DEBUG_LOGS)
            Log.i(TAG, "maybeHandleVrIntentPreNative: preparing for transition");

        // We add a black overlay view so that we can show black while the VR UI is loading.
        // Note that this alone isn't sufficient to prevent 2D UI from showing when
        // auto-presenting WebVR. See comment about the custom animation in {@link
        // getVrIntentOptions}.
        // TODO(crbug.com/775574): This hack doesn't really work to hide the 2D UI on Samsung
        // devices since Chrome gets paused and we prematurely remove the overlay.
        if (sInstance == null || !sInstance.mInVr) {
            VrModuleProvider.getDelegate().addBlackOverlayViewForActivity(activity);
        }

        // Enable VR mode and hide system UI. We do this here so we don't get kicked out of
        // VR mode and to prevent seeing a flash of system UI.
        setVrModeEnabled(activity, true);
        VrModuleProvider.getDelegate().setSystemUiVisibilityForVr(activity);
    }

    /**
     * Asynchronously enable VR mode.
     */
    public static void setVrModeEnabled(Activity activity, boolean enabled) {
        ensureLifecycleObserverInitialized();
        if (enabled) {
            if (sVrModeEnabledActivitys.contains(activity)) return;
            AndroidCompat.setVrModeEnabled(activity, true);
            sVrModeEnabledActivitys.add(activity);
        } else {
            if (!sVrModeEnabledActivitys.contains(activity)) return;
            AndroidCompat.setVrModeEnabled(activity, false);
            sVrModeEnabledActivitys.remove(activity);
        }
    }

    /**
     * Performs pre-inflation VR-related startup.
     */
    public static void doPreInflationStartup(ChromeActivity activity, Bundle savedInstanceState) {
        // We need to explicitly enable VR mode here so that the system doesn't kick us out of VR,
        // or drop us into the 2D-in-VR rendering mode, while we prepare for VR rendering.
        if (VrModuleProvider.getIntentDelegate().isLaunchingIntoVr(
                    activity, activity.getIntent())) {
            setVrModeEnabled(activity, true);
        } else if (savedInstanceState != null && savedInstanceState.getBoolean(IN_VR, false)) {
            // When Chrome is restored from a SavedInstanceState with VR mode still on we need to
            // Explicitly turn VR mode off even though we can't really know for sure whether or not
            // it's currently on.
            AndroidCompat.setVrModeEnabled(activity, false);
            sVrModeEnabledActivitys.remove(activity);
        }
    }

    /**
     * See {@link Activity#onSaveInstanceState(Bundle)}
     */
    public static void onSaveInstanceState(Bundle outState) {
        if (isInVr()) outState.putBoolean(IN_VR, true);
    }

    /**
     * @return A Daydream Api instance, for interacting with Daydream platform features.
     */
    public static VrDaydreamApi getVrDaydreamApi() {
        if (sVrDaydreamApi == null) sVrDaydreamApi = new VrDaydreamApi();
        return sVrDaydreamApi;
    }

    public static boolean isDaydreamReadyDevice() {
        return DaydreamApi.isDaydreamReadyPlatform(ContextUtils.getApplicationContext());
    }

    public static boolean isDaydreamCurrentViewer() {
        if (sInstance != null) return sInstance.isDaydreamCurrentViewerInternal();
        return getVrDaydreamApi().isDaydreamCurrentViewer();
    }

    public static boolean supports2dInVr() {
        Context context = ContextUtils.getApplicationContext();
        return isDaydreamReadyDevice() && DaydreamApi.supports2dInVr(context);
    }

    protected static void enableTestVrShellDelegateOnStartupForTesting() {
        sTestVrShellDelegateOnStartup = true;
    }

    /* package */ static boolean isVrModeEnabled(Activity activity) {
        return sVrModeEnabledActivitys.contains(activity);
    }

    private static boolean activitySupportsPresentation(Activity activity) {
        return activity instanceof ChromeTabbedActivity || activity instanceof CustomTabActivity
                || activity instanceof WebappActivity;
    }

    private static boolean activitySupportsExitFeedback(Activity activity) {
        return activity instanceof ChromeTabbedActivity
                && ChromeFeatureList.isEnabled(ChromeFeatureList.VR_BROWSING_FEEDBACK);
    }

    private static void registerVrAssetsComponentIfDaydreamUser(boolean isDaydreamCurrentViewer) {
        assert !sRegisteredVrAssetsComponent;
        if (isDaydreamCurrentViewer) {
            nativeRegisterVrAssetsComponent();
            sRegisteredVrAssetsComponent = true;
        }
        ChromePreferenceManager.getInstance().writeBoolean(
                ChromePreferenceManager.SHOULD_REGISTER_VR_ASSETS_COMPONENT_ON_STARTUP,
                isDaydreamCurrentViewer);
    }

    private static VrCoreVersionChecker getVrCoreVersionChecker() {
        if (sVrCoreVersionChecker == null) sVrCoreVersionChecker = new VrCoreVersionChecker();
        return sVrCoreVersionChecker;
    }

    // We need a custom Intent for entering VR in order to support VR in Custom Tabs. Custom Tabs
    // are not a singleInstance activity, so they cannot be resumed through Activity PendingIntents,
    // which is the typical way Daydream resumes your Activity. Instead, we use a broadcast intent
    // and then use the broadcast to bring ourselves back to the foreground.
    /* package */ static PendingIntent getEnterVrPendingIntent(ChromeActivity activity) {
        if (sVrBroadcastReceiver != null) sVrBroadcastReceiver.unregister();
        IntentFilter filter = new IntentFilter(VR_ENTRY_RESULT_ACTION);
        VrBroadcastReceiver receiver = new VrBroadcastReceiver(activity);
        // If we set sVrBroadcastReceiver then use it in registerReceiver, findBugs considers this
        // a thread-safety issue since it thinks the receiver isn't fully initialized before being
        // exposed to other threads. This isn't actually an issue in this case, but we need to set
        // sVrBroadcastReceiver after we're done using it here to fix the compile error.
        activity.registerReceiver(receiver, filter);
        sVrBroadcastReceiver = receiver;
        Intent vrIntent = new Intent(VR_ENTRY_RESULT_ACTION);
        vrIntent.setPackage(activity.getPackageName());
        return PendingIntent.getBroadcast(activity, 0, vrIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    /**
     * Registers the Intent to fire after phone inserted into a headset.
     */
    private static void registerDaydreamIntent(final ChromeActivity activity) {
        if (sRegisteredDaydreamHook) return;
        if (!getVrDaydreamApi().registerDaydreamIntent(getEnterVrPendingIntent(activity))) return;
        sRegisteredDaydreamHook = true;
    }

    /**
     * Unregisters the Intent which registered by this context if any.
     */
    private static void unregisterDaydreamIntent() {
        if (!sRegisteredDaydreamHook) return;
        getVrDaydreamApi().unregisterDaydreamIntent();
        sRegisteredDaydreamHook = false;
    }

    private static boolean isVrBrowsingSupported(ChromeActivity activity) {
        return VrModuleProvider.getDelegate().activitySupportsVrBrowsing(activity)
                && !willChangeDensityInVr(activity) && isDaydreamCurrentViewer();
    }

    /**
     * @return Whether or not VR Browsing is currently enabled for the given Activity.
     */
    /* package */ static boolean isVrBrowsingEnabled(ChromeActivity activity, int vrSupportLevel) {
        return isVrBrowsingSupported(activity) && vrSupportLevel == VrSupportLevel.VR_DAYDREAM;
    }

    /* package */ static boolean isInVrSession() {
        Context context = ContextUtils.getApplicationContext();
        // The call to isInVrSession crashes when called on a non-Daydream ready device, so we add
        // the device check (b/77268533).
        try {
            return isDaydreamReadyDevice() && DaydreamApi.isInVrSession(context);
        } catch (Exception ex) {
            Log.e(TAG, "Unable to check if in VR session", ex);
            return false;
        }
    }

    /* package */ static boolean willChangeDensityInVr(ChromeActivity activity) {
        // Only N+ support launching in VR at all, other OS versions don't care about this.
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return false;

        // If the screen density changed while in VR, we have to disable the VR browser as java UI
        // used or created by VR browsing will be broken.
        if (sInstance != null && sInstance.mExpectedDensityChange != 0) return true;
        if (getVrSupportLevel() != VrSupportLevel.VR_DAYDREAM) return false;

        Display display = DisplayAndroidManager.getDefaultDisplayForContext(
                ContextUtils.getApplicationContext());
        DisplayMetrics metrics = new DisplayMetrics();
        display.getRealMetrics(metrics);

        if (activity.getLastActiveDensity() != 0
                && (int) activity.getLastActiveDensity() != metrics.densityDpi) {
            return true;
        }

        if (!deviceCanChangeResolutionForVr()) return false;

        Display.Mode[] modes = display.getSupportedModes();
        // Devices with only one mode won't switch modes while in VR.
        if (modes.length <= 1) return false;
        Display.Mode vr_mode = modes[0];
        for (int i = 1; i < modes.length; ++i) {
            if (modes[i].getPhysicalWidth() > vr_mode.getPhysicalWidth()) vr_mode = modes[i];
        }

        // If we're currently in the mode supported by VR the density won't change.
        // We actually can't use display.getMode() to get the current mode as that just always
        // returns the same mode ignoring the override, so we just check that our current display
        // size is not equal to the vr mode size.
        if (vr_mode.getPhysicalWidth() != metrics.widthPixels
                && vr_mode.getPhysicalWidth() != metrics.heightPixels) {
            return true;
        }
        if (vr_mode.getPhysicalHeight() != metrics.widthPixels
                && vr_mode.getPhysicalHeight() != metrics.heightPixels) {
            return true;
        }
        return false;
    }

    private static boolean deviceCanChangeResolutionForVr() {
        // Samsung devices no longer change density when entering VR on O+.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) return false;
        String model = android.os.Build.MODEL;
        if (SAMSUNG_GALAXY_8_ALT_MODELS.contains(model)) return true;

        // Only Samsung devices change resolution in VR.
        if (!model.startsWith(SAMSUNG_GALAXY_PREFIX)) return false;
        CharSequence modelNumber = model.subSequence(3, 7);
        // Only S8(+) and Note 8 models change resolution in VR.
        if (!SAMSUNG_GALAXY_8_MODELS.contains(modelNumber)) return false;
        return true;
    }

    private static boolean isVrCoreCompatible() {
        VrCoreVersionChecker checker = getVrCoreVersionChecker();
        if (checker == null) return false;
        return checker.getVrCoreCompatibility() == VrCoreCompatibility.VR_READY;
    }

    private static void startFeedback(Tab tab) {
        // TODO(ymalik): This call will connect to the Google Services api which can be slow. Can we
        // connect to it beforehand when we know that we'll be prompting for feedback?
        HelpAndFeedback.getInstance(tab.getActivity())
                .showFeedback(tab.getActivity(), tab.getProfile(), tab.getUrl(),
                        ContextUtils.getApplicationContext().getPackageName() + "."
                                + FEEDBACK_REPORT_TYPE);
    }

    private static void promptForFeedback(final Tab tab) {
        if (tab == null) return;
        final ChromeActivity activity = tab.getActivity();
        SimpleConfirmInfoBarBuilder.Listener listener = new SimpleConfirmInfoBarBuilder.Listener() {
            @Override
            public void onInfoBarDismissed() {}

            @Override
            public boolean onInfoBarButtonClicked(boolean isPrimary) {
                if (isPrimary) {
                    startFeedback(tab);
                } else {
                    VrFeedbackStatus.setFeedbackOptOut(true);
                }
                return false;
            }
        };

        SimpleConfirmInfoBarBuilder.create(tab, listener,
                InfoBarIdentifier.VR_FEEDBACK_INFOBAR_ANDROID, R.drawable.vr_services,
                activity.getString(R.string.vr_shell_feedback_infobar_description),
                activity.getString(R.string.vr_shell_feedback_infobar_feedback_button),
                activity.getString(R.string.no_thanks), true /* autoExpire  */);
    }

    private static void ensureLifecycleObserverInitialized() {
        if (sVrLifecycleObserver != null) return;
        sVrLifecycleObserver = new VrLifecycleObserver();
        ApplicationStatus.registerStateListenerForAllActivities(sVrLifecycleObserver);
    }

    /**
     * Returns the current {@VrSupportLevel}.
     */
    @CalledByNative
    private static int getVrSupportLevel() {
        if (sVrSupportLevel == null) {
            if (!isVrCoreCompatible()) {
                sVrSupportLevel = VrSupportLevel.VR_NEEDS_UPDATE;
            } else if (isDaydreamReadyDevice()) {
                sVrSupportLevel = VrSupportLevel.VR_DAYDREAM;
            } else {
                sVrSupportLevel = VrSupportLevel.VR_CARDBOARD;
            }
        }
        return sVrSupportLevel;
    }

    @CalledByNative
    private static VrShellDelegate getInstance() {
        Activity activity = ApplicationStatus.getLastTrackedFocusedActivity();
        if (!(activity instanceof ChromeActivity)) return null;
        return getInstance((ChromeActivity) activity);
    }

    @SuppressWarnings("unchecked")
    private static VrShellDelegate getInstance(ChromeActivity activity) {
        if (!LibraryLoader.getInstance().isInitialized()) return null;
        if (activity == null || !activitySupportsPresentation(activity)) return null;
        if (sInstance != null) return sInstance;
        ThreadUtils.assertOnUiThread();
        if (sTestVrShellDelegateOnStartup) {
            try {
                // This should only ever be run during tests on standalone devices. Normally, we
                // create a TestVrShellDelegate during pre-test setup after Chrome has started.
                // However, since Chrome is started in VR on standalones, creating a
                // TestVrShellDelegate after startup discards the existing VrShellDelegate instance
                // that's in use, which is bad. So, in those cases, create a TestVrShellDelegate
                // instead of the production version.
                Class clazz = Class.forName("org.chromium.chrome.browser.vr.TestVrShellDelegate");
                Method method = clazz.getMethod("createTestVrShellDelegate", ChromeActivity.class);
                method.invoke(null, activity);
            } catch (Exception e) {
                assert false;
            }
        } else {
            sInstance = new VrShellDelegate(activity);
        }
        return sInstance;
    }

    protected VrShellDelegate(ChromeActivity activity) {
        mActivity = activity;
        // If an activity isn't resumed at the point, it must have been paused.
        mPaused = ApplicationStatus.getStateForActivity(activity) != ActivityState.RESUMED;
        mVisible = activity.hasWindowFocus();
        mNativeVrShellDelegate = nativeInit();
        updateVrSupportLevel(null);
        mFeedbackFrequency = VrFeedbackStatus.getFeedbackFrequency();
        ensureLifecycleObserverInitialized();
        if (!mPaused) onResume();
        sInstance = this;
    }

    public void onActivityStateChange(Activity activity, int newState) {
        switch (newState) {
            case ActivityState.DESTROYED:
                if (activity == mActivity) destroy();
                break;
            case ActivityState.PAUSED:
                if (activity == mActivity) onPause();
                // Other activities should only pause while we're paused due to Android lifecycle.
                assert mPaused;
                break;
            case ActivityState.STOPPED:
                if (activity == mActivity) onStop();
                break;
            case ActivityState.STARTED:
                if (activity == mActivity) onStart();
                break;
            case ActivityState.RESUMED:
                if (!activitySupportsPresentation(activity)) return;
                if (!(activity instanceof ChromeActivity)) return;
                swapHostActivity((ChromeActivity) activity, true /* disableVrMode */);
                onResume();
                break;
            default:
                break;
        }
    }

    // Called when an activity that supports VR is resumed, and attaches VrShellDelegate to that
    // activity.
    private void swapHostActivity(ChromeActivity activity, boolean disableVrMode) {
        assert mActivity != null;
        if (mActivity == activity) return;
        if (mInVr) shutdownVr(disableVrMode, false /* stayingInChrome */);
        mActivity = activity;
    }

    private void maybeUpdateVrSupportLevel() {
        // If we're on Daydream support level, Chrome will get restarted by Android in response to
        // VrCore being updated/downgraded, so we don't need to check.
        if (getVrSupportLevel() == VrSupportLevel.VR_DAYDREAM) return;
        int version = getVrCorePackageVersion();
        // If VrCore package hasn't changed, no need to update.
        if (version == mCachedVrCorePackageVersion
                && !(mShowVrServicesUpdatePrompt != null && mShowVrServicesUpdatePrompt)) {
            return;
        }
        updateVrSupportLevel(version);
    }

    private int getVrCorePackageVersion() {
        return PackageUtils.getPackageVersion(
                ContextUtils.getApplicationContext(), VrCoreVersionChecker.VR_CORE_PACKAGE_ID);
    }

    private int getGvrKeyboardPackageVersion() {
        return PackageUtils.getPackageVersion(
                ContextUtils.getApplicationContext(), GVR_KEYBOARD_PACKAGE_ID);
    }

    /**
     * Updates sVrSupportLevel to the correct value as VR support can change over time.
     */
    private void updateVrSupportLevel(Integer vrCorePackageVersion) {
        sVrSupportLevel = null;
        if (getVrSupportLevel() != VrSupportLevel.VR_NEEDS_UPDATE) return;
        if (vrCorePackageVersion == null) vrCorePackageVersion = getVrCorePackageVersion();
        mCachedVrCorePackageVersion = vrCorePackageVersion;
        promptToUpdateVrServices();
    }

    private void promptToUpdateVrServices() {
        assert getVrSupportLevel() == VrSupportLevel.VR_NEEDS_UPDATE;
        Tab tab = mActivity.getActivityTab();
        if (tab == null) return;

        int vrCoreCompatibility = getVrCoreVersionChecker().getVrCoreCompatibility();

        String infobarText;
        String buttonText;
        if (vrCoreCompatibility == VrCoreCompatibility.VR_NOT_AVAILABLE) {
            // Supported, but not installed. Ask user to install instead of upgrade.
            infobarText = mActivity.getString(R.string.vr_services_check_infobar_install_text);
            buttonText = mActivity.getString(R.string.vr_services_check_infobar_install_button);
        } else if (vrCoreCompatibility == VrCoreCompatibility.VR_OUT_OF_DATE) {
            infobarText = mActivity.getString(R.string.vr_services_check_infobar_update_text);
            buttonText = mActivity.getString(R.string.vr_services_check_infobar_update_button);
        } else {
            Log.e(TAG, "Unknown VrCore compatibility: " + vrCoreCompatibility);
            return;
        }

        SimpleConfirmInfoBarBuilder.Listener listener = new SimpleConfirmInfoBarBuilder.Listener() {
            @Override
            public void onInfoBarDismissed() {}

            @Override
            public boolean onInfoBarButtonClicked(boolean isPrimary) {
                mActivity.startActivityForResult(
                        new Intent(Intent.ACTION_VIEW, Uri.parse(VR_CORE_MARKET_URI)),
                        VR_SERVICES_UPDATE_RESULT);
                return false;
            }
        };
        SimpleConfirmInfoBarBuilder.create(tab, listener,
                InfoBarIdentifier.VR_SERVICES_UPGRADE_ANDROID, R.drawable.vr_services, infobarText,
                buttonText, null, true);
    }

    @VisibleForTesting
    protected boolean isVrBrowsingEnabled() {
        return isVrBrowsingEnabled(mActivity, getVrSupportLevel());
    }

    private void onVrServicesMaybeUpdated() {
        if (mCachedVrCorePackageVersion == getVrCorePackageVersion()) return;
        ApplicationLifetime.terminate(true);
    }

    private void onGvrKeyboardMaybeUpdated() {
        if (mCachedGvrKeyboardPackageVersion == getGvrKeyboardPackageVersion()) return;
        ApplicationLifetime.terminate(true);
    }

    /**
     * Returns whether the device has support for Daydream.
     */
    /* package */ boolean hasDaydreamSupport() {
        return getVrSupportLevel() == VrSupportLevel.VR_DAYDREAM;
    }

    private void maybeSetPresentResult(boolean result) {
        if (mNativeVrShellDelegate == 0 || !mRequestedWebVr) return;
        nativeSetPresentResult(mNativeVrShellDelegate, result);
        mRequestedWebVr = false;
    }

    /**
     * Handle a successful VR DON flow, entering VR in the process unless we're unable to.
     * @return False if VR entry failed.
     */
    private boolean enterVrAfterDon() {
        if (mNativeVrShellDelegate == 0) return false;
        if (!canEnterVr()) return false;

        // If headset insertion was performed while a page was listening for vrdisplayactivate,
        // we assume it wants to request presentation. Go into WebVR mode tentatively. If the page
        // doesn't request presentation in the vrdisplayactivate handler we will exit presentation
        // later.
        if (mActivateFromHeadsetInsertion) {
            assert !mRequestedWebVr;
            assert !mStartedFromVrIntent;
        }
        enterVr(mActivateFromHeadsetInsertion);
        if (mActivateFromHeadsetInsertion && mListeningForWebVrActivate) {
            nativeDisplayActivate(mNativeVrShellDelegate);
            mActivateFromHeadsetInsertion = false;
        }

        // The user has successfully completed a DON flow.
        RecordUserAction.record("VR.DON");

        return true;
    }

    private void enterVr(final boolean tentativeWebVrMode) {
        // We should only enter VR when we're the resumed Activity or our changes to things like
        // system UI flags might get lost.
        assert !mPaused;
        assert mNativeVrShellDelegate != 0;
        if (mInVr) return;
        mInVr = true;
        setVrModeEnabled(mActivity, true);

        setWindowModeForVr();

        // We assume that we triggered the DON flow already for Daydream viewers. If that changes,
        // we need to make sure not to report success/fail to WebXR until after the DON flow runs.
        assert mDonSucceeded || !isDaydreamCurrentViewerInternal();

        mDonSucceeded = false;
        if (!createVrShell()) {
            cancelPendingVrEntry();
            mInVr = false;
            getVrDaydreamApi().launchVrHomescreen();
            return;
        }
        mExitedDueToUnsupportedMode = false;

        addVrViews();
        // Make sure that assets component is registered when creating native VR shell.
        if (!sRegisteredVrAssetsComponent) {
            registerVrAssetsComponentIfDaydreamUser(isDaydreamCurrentViewer());
        }
        boolean webVrMode = mRequestedWebVr || tentativeWebVrMode;
        mVrShell.initializeNative(webVrMode, VrModuleProvider.getDelegate().bootsToVr());
        mVrShell.setWebVrModeEnabled(webVrMode);

        // We're entering VR, but not in WebVr mode.
        mVrBrowserUsed = !webVrMode;

        // resume needs to be called on GvrLayout after initialization to make sure DON flow works
        // properly.
        if (mVisible) mVrShell.resume();
        mVrShell.getContainer().setOnSystemUiVisibilityChangeListener(this);

        maybeSetPresentResult(true);

        VrModuleProvider.onEnterVr();
    }

    private void onVrIntentUnsupported() {
        // If entering VR is unsupported for some reason, clean up what we did in
        // maybeHandleVrIntentPreNative.
        assert !mInVr;
        mStartedFromVrIntent = false;
        cancelPendingVrEntry();

        // Some Samsung devices change the screen density after exiting VR mode which causes
        // us to restart Chrome with the VR intent that originally started it. We don't want to
        // enable VR mode when the user opens Chrome again in 2D mode, so we remove VR specific
        // extras.
        VrModuleProvider.getIntentDelegate().removeVrExtras(mActivity.getIntent());

        // We may still be showing the STAY_HIDDEN animation, so cancel it if necessary.
        cancelStartupAnimationIfNeeded();
    }

    private void onNewVrIntent() {
        // We set the the system UI in maybeHandleVrIntentPreNative, so make sure we restore it when
        // we exit VR, or cancel VR entry.
        mRestoreSystemUiVisibility = true;

        // Nothing to do if we were launched by an internal intent.
        if (mInternalIntentUsedToStartVr) {
            mInternalIntentUsedToStartVr = false;

            // TODO(mthiesse): This shouldn't be necessary. This is another instance of b/65681875,
            // where the intent is received after we're resumed.
            if (mInVr) return;

            // This is extremely unlikely in practice. Some code must have called shutdownVR() while
            // we were entering VR through NFC insertion.
            if (!mDonSucceeded) cancelPendingVrEntry();
            return;
        }

        if (VrDelegate.USE_HIDE_ANIMATION) mNeedsAnimationCancel = true;

        if (!isVrBrowsingSupported(mActivity)) {
            onVrIntentUnsupported();
            return;
        }

        if (!mInVr) nativeRecordVrStartAction(mNativeVrShellDelegate, VrStartAction.INTENT_LAUNCH);

        mStartedFromVrIntent = true;
        // Setting DON succeeded will cause us to enter VR when resuming.
        mDonSucceeded = true;

        if (!mPaused) {
            // Note that canceling the animation below is what causes us to enter VR mode. We start
            // an intermediate activity to cancel the animation which causes onPause and onResume to
            // be called and we enter VR mode in onResume (because we set the mEnterVrOnStartup bit
            // above). If Chrome is already running, onResume which will be called after
            // VrShellDelegate#onNewIntentWithNative which will cancel the animation and enter VR
            // after that.
            if (!cancelStartupAnimationIfNeeded()) {
                // If we didn't cancel the startup animation, we won't be getting another onResume
                // call, so enter VR here.
                handleDonFlowSuccess();
                runPendingExitVrTask();
            }
        }
    }

    private void runPendingExitVrTask() {
        if (mPendingExitVrRequest == null) return;
        new Handler().post(mPendingExitVrRequest);
        mPendingExitVrRequest = null;
    }

    @Override
    public void onSystemUiVisibilityChange(int visibility) {
        if (mInVr && !isWindowModeCorrectForVr()) {
            setWindowModeForVr();
        }
    }

    @Override
    public boolean canUnlockOrientation(Activity activity, int defaultOrientation) {
        if (mActivity == activity && mRestoreOrientation != null) {
            mRestoreOrientation = defaultOrientation;
            return false;
        }
        return true;
    }

    @Override
    public boolean canLockOrientation() {
        return false;
    }

    public boolean hasAudioPermission() {
        return mActivity.getWindowAndroid().hasPermission(android.Manifest.permission.RECORD_AUDIO);
    }

    private boolean isWindowModeCorrectForVr() {
        int flags = mActivity.getWindow().getDecorView().getSystemUiVisibility();
        int orientation = mActivity.getResources().getConfiguration().orientation;
        // Mask the flags to only those that we care about.
        return (flags & VrDelegate.VR_SYSTEM_UI_FLAGS) == VrDelegate.VR_SYSTEM_UI_FLAGS
                && orientation == Configuration.ORIENTATION_LANDSCAPE;
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    private void setWindowModeForVr() {
        // Decouple the compositor size from the view size, or we'll get an unnecessary resize due
        // to the orientation change when entering VR, then another resize once VR has settled on
        // the content size.
        if (mActivity.getCompositorViewHolder() != null) {
            mActivity.getCompositorViewHolder().onEnterVr();
        }
        ScreenOrientationProvider.setOrientationDelegate(this);

        // Hide system UI.
        VrModuleProvider.getDelegate().setSystemUiVisibilityForVr(mActivity);

        // Set correct orientation.
        if (mRestoreOrientation == null) {
            mRestoreOrientation = mActivity.getRequestedOrientation();
        }

        mRestoreSystemUiVisibility = true;

        mActivity.getWindow().getAttributes().rotationAnimation =
                WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    private void restoreWindowMode() {
        ScreenOrientationProvider.setOrientationDelegate(null);
        mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        // Restore orientation.
        if (mRestoreOrientation != null) mActivity.setRequestedOrientation(mRestoreOrientation);
        mRestoreOrientation = null;

        // Restore system UI visibility.
        if (mRestoreSystemUiVisibility) {
            int flags = mActivity.getWindow().getDecorView().getSystemUiVisibility();
            mActivity.getWindow().getDecorView().setSystemUiVisibility(
                    flags & ~VrDelegate.VR_SYSTEM_UI_FLAGS);
        }
        mRestoreSystemUiVisibility = false;
        if (mActivity.getCompositorViewHolder() != null) {
            mActivity.getCompositorViewHolder().onExitVr();
        }

        mActivity.getWindow().getAttributes().rotationAnimation =
                WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
    }

    /* package */ boolean canEnterVr() {
        if (getVrSupportLevel() <= VrSupportLevel.VR_NEEDS_UPDATE) return false;

        // If VR browsing is not enabled and this is not a WebXR request, then return false.
        boolean presenting = mRequestedWebVr || mActivateFromHeadsetInsertion;
        if (!isVrBrowsingEnabled() && !presenting) return false;
        return true;
    }

    @CalledByNative
    private void presentRequested() {
        if (VrDelegate.DEBUG_LOGS) Log.i(TAG, "WebVR page requested presentation");
        mRequestedWebVr = true;
        if (VrModuleProvider.getDelegate().bootsToVr() && !mInVr) {
            maybeSetPresentResult(false);
            return;
        }
        switch (enterVrInternal()) {
            case EnterVRResult.NOT_NECESSARY:
                mVrShell.setWebVrModeEnabled(true);
                maybeSetPresentResult(true);
                break;
            case EnterVRResult.CANCELLED:
                maybeSetPresentResult(false);
                break;
            case EnterVRResult.REQUESTED:
                break;
            case EnterVRResult.SUCCEEDED:
                maybeSetPresentResult(true);
                break;
            default:
                Log.e(TAG, "Unexpected enum.");
        }
    }

    /**
     * Enters VR Shell if necessary, displaying browser UI and tab contents in VR.
     */
    @EnterVRResult
    private int enterVrInternal() {
        if (mPaused) return EnterVRResult.CANCELLED;
        if (mInVr) return EnterVRResult.NOT_NECESSARY;

        // Update VR support level as it can change at runtime
        maybeUpdateVrSupportLevel();
        if (!canEnterVr()) return EnterVRResult.CANCELLED;
        if (getVrSupportLevel() == VrSupportLevel.VR_DAYDREAM
                && isDaydreamCurrentViewerInternal()) {
            // TODO(mthiesse): This is a workaround for b/66486878 (see also crbug.com/767594).
            // We have to trigger the DON flow before setting VR mode enabled to prevent the DON
            // flow from failing on the S8/S8+.
            // Due to b/66493165, we also can't create our VR UI before the density has changed,
            // so we can't trigger the DON flow by resuming the GvrLayout. This basically means that
            // calling launchInVr on ourself is the only viable option for getting into VR on the
            // S8/S8+.
            // This also fixes the issue tracked in crbug.com/767944, so this should not be removed
            // until the root cause of that has been found and fixed.
            getVrDaydreamApi().launchInVr(getEnterVrPendingIntent(mActivity));
            mProbablyInDon = true;
        } else {
            enterVr(false);
        }
        return EnterVRResult.REQUESTED;
    }

    private void requestToExitVrInternal(OnExitVrRequestListener listener,
            @UiUnsupportedMode int reason, boolean showExitPromptBeforeDoff) {
        assert listener != null;
        if (VrModuleProvider.getDelegate().bootsToVr()) {
            setVrModeEnabled(mActivity, false);
            listener.onSucceeded();
            return;
        }

        // If we are currently processing another request, deny the request.
        if (mOnExitVrRequestListener != null) {
            listener.onDenied();
            return;
        }
        mOnExitVrRequestListener = listener;
        mShowingExitVrPrompt = showExitPromptBeforeDoff;
        mVrShell.requestToExitVr(reason, showExitPromptBeforeDoff);
    }

    private void exitWebVRAndClearState() {
        exitWebVRPresent();
        mRequestedWebVr = false;
    }

    @CalledByNative
    /* package */ void exitWebVRPresent() {
        if (!mInVr) return;

        if (!isVrBrowsingEnabled()) {
            if (isDaydreamCurrentViewerInternal()) {
                getVrDaydreamApi().launchVrHomescreen();
            } else {
                shutdownVr(true /* disableVrMode */, true /* stayingInChrome */);
            }
        } else {
            mVrBrowserUsed = true;
            mVrShell.setWebVrModeEnabled(false);
        }
    }

    private boolean cancelStartupAnimationIfNeeded() {
        if (!mNeedsAnimationCancel) return false;
        if (VrDelegate.DEBUG_LOGS) Log.e(TAG, "canceling startup animation");
        mCancellingEntryAnimation = true;
        Bundle options = ActivityOptions.makeCustomAnimation(mActivity, 0, 0).toBundle();
        Intent intent = VrModuleProvider.getIntentDelegate().setupVrIntent(
                new Intent(mActivity, VrCancelAnimationActivity.class));
        // We don't want this to run in a new task stack, or we may end up resuming the wrong
        // Activity when the VrCancelAnimationActivity finishes.
        intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK);
        mActivity.startActivity(intent, options);
        mNeedsAnimationCancel = false;
        return true;
    }

    private boolean maybeExitVrToUpdateVrServices() {
        if (!mDonSucceeded || getVrSupportLevel() != VrSupportLevel.VR_NEEDS_UPDATE) {
            return false;
        }
        // This means that we were started in VR mode but the vr services are out of date. We should
        // exit VR and prompt the user to update.
        if (VrDelegate.DEBUG_LOGS) Log.i(TAG, "VR services update needed");
        mShowingDoffForGvrUpdate = true;
        showDoff(false /* optional */);
        mDonSucceeded = false;
        return true;
    }

    @VisibleForTesting
    protected void onResume() {
        if (VrDelegate.DEBUG_LOGS) Log.i(TAG, "onResume");
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) return;
        if (!mTestWorkaroundDontCancelVrEntryOnResume) {
            mMaybeActivateAfterHeadsetInsertion = false;
        }
        if (mNeedsAnimationCancel) {
            // At least on some devices, like the Samsung S8+, a Window animation is run after our
            // Activity is shown that fades between a stale screenshot from before pausing to the
            // currently rendered content. It's impossible to cancel window animations, and in order
            // to modify the animation we would need to set up the desired animations before
            // calling setContentView, which we can't do because it would affect non-VR usage.
            // To work around this, we keep the stay_hidden animation active until the window
            // animation of the stale screenshot finishes and our black overlay is shown. We then
            // cancel the stay_hidden animation, revealing our black overlay, which we then replace
            // with VR UI.
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return;
            // Just in case any platforms/users modify the window animation scale, we'll multiply
            // our wait time by that scale value.
            float scale = Settings.Global.getFloat(
                    mActivity.getContentResolver(), Settings.Global.WINDOW_ANIMATION_SCALE, 1.0f);
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    cancelStartupAnimationIfNeeded();
                }
            }, (long) (WINDOW_FADE_ANIMATION_DURATION_MS * scale));
            return;
        }

        mPaused = false;
        mCancellingEntryAnimation = false;

        // We call resume here to be symmetric with onPause in case we get paused/resumed without
        // being hidden/shown. However, we still don't want to resume if we're not visible to avoid
        // doing VR rendering that won't be seen.
        if (mInVr && mVisible) mVrShell.resume();

        maybeUpdateVrSupportLevel();

        // Shouldn't handle VR Intents pre-Daydream.
        assert(getVrSupportLevel() == VrSupportLevel.VR_DAYDREAM || !mStartedFromVrIntent);

        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
        try {
            if (mNativeVrShellDelegate != 0) nativeOnResume(mNativeVrShellDelegate);
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }

        if (isVrBrowsingEnabled()) {
            // Perform slow initialization asynchronously.
            new Handler().post(new Runnable() {
                @Override
                public void run() {
                    if (!mPaused) registerDaydreamIntent(mActivity);
                    if (!sRegisteredVrAssetsComponent) {
                        registerVrAssetsComponentIfDaydreamUser(isDaydreamCurrentViewerInternal());
                    }
                }
            });
        }

        if (mDonSucceeded) {
            handleDonFlowSuccess();
        } else {
            if (mProbablyInDon && !mTestWorkaroundDontCancelVrEntryOnResume) {
                // This means the user backed out of the DON flow, and we won't be entering VR.
                maybeSetPresentResult(false);

                shutdownVr(true, false);
            }
            // If we were resumed at the wrong density, we need to trigger activity recreation.
            if (!mInVr && mExpectedDensityChange != 0
                    && (mActivity.getResources().getConfiguration().densityDpi
                               != mExpectedDensityChange)) {
                mActivity.recreate();
            }
        }

        mProbablyInDon = false;
        mShowVrServicesUpdatePrompt = null;

        runPendingExitVrTask();
    }

    private void handleDonFlowSuccess() {
        setWindowModeForVr();
        if (mInVr) {
            maybeSetPresentResult(true);
            mDonSucceeded = false;
            assert !mActivateFromHeadsetInsertion;
            return;
        }
        if (maybeExitVrToUpdateVrServices()) return;
        // If we fail to enter VR when we should have entered VR, return to the home screen.
        if (!enterVrAfterDon()) {
            cancelPendingVrEntry();
            getVrDaydreamApi().launchVrHomescreen();
        }
    }

    // Android lifecycle doesn't guarantee that this will be called after onResume (though it
    // will usually be), so make sure anything we do here can happen before or after
    // onResume.
    private void onActivityShown() {
        mVisible = true;

        // Only resume VrShell once we're visible so that we don't start rendering before being
        // visible and delaying startup.
        if (mInVr && !mPaused) mVrShell.resume();
    }

    private void onActivityHidden() {
        mVisible = false;
        // In case we're hidden before onPause is called, we pause here. Duplicate calls to pause
        // are safe.
        if (mInVr) mVrShell.pause();
    }

    private void onPause() {
        if (VrDelegate.DEBUG_LOGS) Log.i(TAG, "onPause");
        mPaused = true;
        if (mCancellingEntryAnimation) return;
        unregisterDaydreamIntent();
        if (getVrSupportLevel() <= VrSupportLevel.VR_NEEDS_UPDATE) return;

        if (mMaybeActivateAfterHeadsetInsertion) {
            mClearMaybeActivateHandler.removeCallbacksAndMessages(null);
        }

        if (mInVr) mVrShell.pause();
        if (mNativeVrShellDelegate != 0) nativeOnPause(mNativeVrShellDelegate);

        mIsDaydreamCurrentViewer = null;
    }

    private void onStart() {
        mMaybeActivateAfterHeadsetInsertion = false;
        if (mDonSucceeded) setWindowModeForVr();

        // This handles the case where Chrome was paused in VR (ie the user navigated to DD home or
        // something), then exited VR and resumed Chrome in 2D. Chrome is still showing VR UI but
        // the user is no longer in a VR session.
        if (mInVr && !isInVrSession()) {
            shutdownVr(true, false);
        }

        // Note that we do not turn VR mode on here for two reasons.
        // 1. If we're in VR, it should already be on and won't get turned off until we explicitly
        // turn it off for this Activity.
        // 2. Turning VR mode on breaks popup showing code, which relies on VR mode sometimes being
        // off while in VR.
    }

    private void onStop() {
        if (VrDelegate.DEBUG_LOGS) Log.i(TAG, "onStop");
        assert !mCancellingEntryAnimation;
    }

    private boolean onBackPressedInternal() {
        if (getVrSupportLevel() <= VrSupportLevel.VR_NEEDS_UPDATE) return false;
        cancelPendingVrEntry();
        if (!mInVr) return false;
        // Back button should be handled the same way as the close button.
        getVrCloseButtonListener().run();
        return true;
    }

    /**
     * @return Whether the user is currently seeing the DOFF screen.
     */
    /* package */ boolean showDoff(boolean optional) {
        assert !mShowingDaydreamDoff;
        if (!isDaydreamCurrentViewerInternal()) return false;

        if (supports2dInVr()) {
            setVrModeEnabled(mActivity, false);
            callOnExitVrRequestListener(true);
            return true;
        }

        try {
            if (getVrDaydreamApi().exitFromVr(mActivity, EXIT_VR_RESULT, new Intent())) {
                mShowingDaydreamDoff = true;
                mDoffOptional = optional;
                return true;
            }
        } catch (IllegalArgumentException | SecurityException e) {
            // DOFF calls can unpredictably throw exceptions if VrCore doesn't think Chrome is
            // the active component, for example.
        }
        if (!optional) getVrDaydreamApi().launchVrHomescreen();
        return false;
    }

    private void onExitVrResult(boolean success) {
        if (VrDelegate.DEBUG_LOGS) Log.i(TAG, "returned from DOFF, success: " + success);

        // We may have manually handled the exit early by swapping to another Chrome activity that
        // supports VR while in the DOFF activity. If that happens we want to exit early when the
        // real DOFF flow calls us back.
        if (!mShowingDaydreamDoff) return;

        // If Doff is not optional and user backed out, launch DD home. We can't re-trigger doff
        // here because we're not yet the active VR component and Daydream will throw a Security
        // Exception.
        if (!mDoffOptional && !success) getVrDaydreamApi().launchVrHomescreen();

        mShowingDaydreamDoff = false;

        if (mShowingDoffForGvrUpdate) mShowVrServicesUpdatePrompt = success;

        if (success) shutdownVr(true /* disableVrMode */, true /* stayingInChrome */);

        callOnExitVrRequestListener(success);
        mShowingDoffForGvrUpdate = false;
    }

    // Caches whether the current viewer is Daydream for performance.
    private boolean isDaydreamCurrentViewerInternal() {
        if (mIsDaydreamCurrentViewer == null) {
            mIsDaydreamCurrentViewer = getVrDaydreamApi().isDaydreamCurrentViewer();
        }
        return mIsDaydreamCurrentViewer;
    }

    @CalledByNative
    private void setListeningForWebVrActivate(boolean listening) {
        if (VrDelegate.DEBUG_LOGS)
            Log.i(TAG, "WebVR page listening for vrdisplayactivate: " + listening);
        // Non-Daydream devices do not have the concept of activation.
        if (getVrSupportLevel() != VrSupportLevel.VR_DAYDREAM) return;
        if (mListeningForWebVrActivate == listening) return;
        mListeningForWebVrActivate = listening;
        if (mListeningForWebVrActivate) {
            registerDaydreamIntent(mActivity);
            if (mNeedsAnimationCancel || mCancellingEntryAnimation) return;
            if (mActivateFromHeadsetInsertion) {
                // Dispatch vrdisplayactivate so that the WebVr page can call requestPresent
                // to start presentation.
                nativeDisplayActivate(mNativeVrShellDelegate);
                mActivateFromHeadsetInsertion = false;
            }
        } else {
            if (!canEnterVr()) unregisterDaydreamIntent();
            // When the active web page has a vrdisplayactivate event handler, and the phone is
            // inserted into the headset, a vrdisplayactive event should be fired once DON flow
            // is finished. However, the DON flow will pause our activity, which makes the active
            // page lose focus and report that it can't handle displayActivate.
            // Because of the order of onPause events running, we can't check for
            // mListeningForWebVrActivate in onPause() as we may or may not already have lost focus.
            // We need to remember that
            mMaybeActivateAfterHeadsetInsertion = !mInVr && !mRequestedWebVr;
            if (!mPaused) {
                mClearMaybeActivateHandler.post(
                        () -> { mMaybeActivateAfterHeadsetInsertion = false; });
            }
        }
    }

    private void cancelPendingVrEntry() {
        if (VrDelegate.DEBUG_LOGS) Log.i(TAG, "cancelPendingVrEntry");
        VrModuleProvider.getDelegate().removeBlackOverlayView(mActivity, false /* animate */);
        mDonSucceeded = false;
        mActivateFromHeadsetInsertion = false;
        maybeSetPresentResult(false);
        if (!mShowingDaydreamDoff) {
            setVrModeEnabled(mActivity, false);
            restoreWindowMode();
        }
    }

    /**
     * Exits VR Shell, performing all necessary cleanup.
     */
    private void shutdownVr(boolean disableVrMode, boolean stayingInChrome) {
        if (VrDelegate.DEBUG_LOGS) Log.i(TAG, "shuttdown VR");
        cancelPendingVrEntry();

        if (!mInVr) return;
        if (mShowingDaydreamDoff) {
            onExitVrResult(true);
            return;
        }
        mInVr = false;

        // Some Samsung devices change the screen density after exiting VR mode which causes
        // us to restart Chrome with the VR intent that originally started it. We don't want to
        // enable VR mode again, so we remove VR specific extras.
        VrModuleProvider.getIntentDelegate().removeVrExtras(mActivity.getIntent());

        // The user has exited VR.
        RecordUserAction.record("VR.DOFF");

        if (disableVrMode) setVrModeEnabled(mActivity, false);

        // We get crashes on Android K related to surfaces if we manipulate the view hierarchy while
        // finishing.
        if (mActivity.isFinishing()) return;

        restoreWindowMode();
        mVrShell.pause();
        removeVrViews();
        destroyVrShell();

        promptForFeedbackIfNeeded(stayingInChrome);

        // User exited VR (via something like the system back button) while looking at the exit VR
        // prompt.
        if (mShowingExitVrPrompt) callOnExitVrRequestListener(true);

        VrModuleProvider.onExitVr();
    }

    private void callOnExitVrRequestListener(boolean success) {
        if (mOnExitVrRequestListener != null) {
            if (success) {
                mOnExitVrRequestListener.onSucceeded();
            } else {
                mOnExitVrRequestListener.onDenied();
            }
        }
        mOnExitVrRequestListener = null;
    }

    /* package */ void onExitVrRequestResult(boolean shouldExit) {
        assert mOnExitVrRequestListener != null;
        mShowingExitVrPrompt = false;
        if (shouldExit) {
            mExitedDueToUnsupportedMode = true;
            if (!showDoff(true /* optional */)) callOnExitVrRequestListener(false);
        } else {
            callOnExitVrRequestListener(false);
        }
    }

    /**
     * Returns the callback for the user-triggered close button to exit VR mode.
     */
    /* package */ Runnable getVrCloseButtonListener() {
        if (mCloseButtonListener != null) return mCloseButtonListener;
        mCloseButtonListener = new Runnable() {
            @Override
            public void run() {
                shutdownVr(true /* disableVrMode */, true /* stayingInChrome */);
            }
        };
        return mCloseButtonListener;
    }

    /**
     * Returns the callback for the user-triggered close button to exit VR mode.
     */
    /* package */ Runnable getVrSettingsButtonListener() {
        if (mSettingsButtonListener != null) return mSettingsButtonListener;
        mSettingsButtonListener = new Runnable() {
            @Override
            public void run() {
                shutdownVr(true /* disableVrMode */, false /* stayingInChrome */);

                // Launch Daydream settings.
                GvrUiLayout.launchOrInstallGvrApp(mActivity);
            }
        };
        return mSettingsButtonListener;
    }

    /**
     * Prompts the user to enter feedback for their VR Browsing experience.
     */
    private void promptForFeedbackIfNeeded(boolean stayingInChrome) {
        // We only prompt for feedback if:
        // 1) The user hasn't explicitly opted-out of it in the past
        // 2) The user has performed VR browsing
        // 3) The user is exiting VR and going back into 2D Chrome
        // 4) We're not exiting to complete an unsupported VR action in 2D (e.g. viewing PageInfo)
        // 5) Every n'th visit (where n = mFeedbackFrequency)

        if (!activitySupportsExitFeedback(mActivity)) return;
        if (!stayingInChrome) return;
        if (VrFeedbackStatus.getFeedbackOptOut()) return;
        if (!mVrBrowserUsed) return;
        if (mExitedDueToUnsupportedMode) return;

        int exitCount = VrFeedbackStatus.getUserExitedAndEntered2DCount();
        VrFeedbackStatus.setUserExitedAndEntered2DCount((exitCount + 1) % mFeedbackFrequency);

        if (exitCount > 0) return;

        promptForFeedback(mActivity.getActivityTab());
    }

    /* package */ void promptForKeyboardUpdate() {
        mCachedGvrKeyboardPackageVersion = getGvrKeyboardPackageVersion();
        mActivity.startActivityForResult(
                new Intent(Intent.ACTION_VIEW, Uri.parse(GVR_KEYBOARD_MARKET_URI)),
                GVR_KEYBOARD_UPDATE_RESULT);
    }

    @VisibleForTesting
    protected boolean canLaunch2DIntentsInternal() {
        return supports2dInVr() && !sVrModeEnabledActivitys.contains(sInstance.mActivity);
    }

    @VisibleForTesting
    protected boolean createVrShell() {
        assert mVrShell == null;
        if (mActivity.getCompositorViewHolder() == null) return false;
        TabModelSelector tabModelSelector = mActivity.getTabModelSelector();
        if (tabModelSelector == null) return false;
        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
        try {
            mVrShell = new VrShell(mActivity, this, tabModelSelector);
        } catch (VrUnsupportedException e) {
            return false;
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }
        return true;
    }

    private void addVrViews() {
        FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
        LayoutParams params = new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        decor.addView(mVrShell.getContainer(), params);
        // If the overlay exists, make sure to hide the GvrLayout behind it.
        View overlay = mActivity.getWindow().findViewById(R.id.vr_overlay_view);
        if (overlay != null) overlay.bringToFront();
        mActivity.onEnterVr();
    }

    @VisibleForTesting
    protected boolean isBlackOverlayVisible() {
        View overlay = mActivity.getWindow().findViewById(R.id.vr_overlay_view);
        return overlay != null;
    }

    private void removeVrViews() {
        mActivity.onExitVr();
        FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
        decor.removeView(mVrShell.getContainer());
    }

    /**
     * Clean up VrShell, and associated native objects.
     */
    private void destroyVrShell() {
        if (mVrShell != null) {
            mVrShell.getContainer().setOnSystemUiVisibilityChangeListener(null);
            mVrShell.teardown();
            mVrShell = null;
        }
    }

    /**
     * @param api The VrDaydreamApi object this delegate will use instead of the default one
     */
    @VisibleForTesting
    protected void overrideDaydreamApi(VrDaydreamApi api) {
        sVrDaydreamApi = api;
    }

    /**
     * @return The VrShell for the VrShellDelegate instance
     */
    @VisibleForTesting
    protected VrShell getVrShell() {
        return mVrShell;
    }

    /**
     * @param versionChecker The VrCoreVersionChecker object this delegate will use
     */
    @VisibleForTesting
    protected void overrideVrCoreVersionChecker(VrCoreVersionChecker versionChecker) {
        sVrCoreVersionChecker = versionChecker;
        updateVrSupportLevel(null);
    }

    /**
     * @param frequency Sets how often to show the feedback prompt.
     */
    @VisibleForTesting
    protected void setFeedbackFrequency(int frequency) {
        mFeedbackFrequency = frequency;
    }

    @VisibleForTesting
    protected boolean isListeningForWebVrActivate() {
        return mListeningForWebVrActivate;
    }

    @VisibleForTesting
    protected boolean isVrEntryComplete() {
        return mInVr && !mProbablyInDon && getVrShell().hasUiFinishedLoading();
    }

    @VisibleForTesting
    protected boolean isShowingDoff() {
        return mShowingDaydreamDoff;
    }

    @VisibleForTesting
    protected void onBroadcastReceived() {}

    @VisibleForTesting
    protected void setExpectingIntent(boolean expectingIntent) {}

    /**
     * @return Pointer to the native VrShellDelegate object.
     */
    @CalledByNative
    private long getNativePointer() {
        return mNativeVrShellDelegate;
    }

    @CalledByNative
    private long getVrCoreInfo() {
        assert getVrCoreVersionChecker() != null;
        return getVrCoreVersionChecker().makeNativeVrCoreInfo();
    }

    private void destroy() {
        if (sInstance == null) return;
        shutdownVr(false /* disableVrMode */, false /* stayingInChrome */);
        if (mNativeVrShellDelegate != 0) nativeDestroy(mNativeVrShellDelegate);
        mNativeVrShellDelegate = 0;
        sInstance = null;
    }

    private native long nativeInit();
    private static native void nativeOnLibraryAvailable();
    private native void nativeSetPresentResult(long nativeVrShellDelegate, boolean result);
    private native void nativeRecordVrStartAction(long nativeVrShellDelegate, int startAction);
    private native void nativeDisplayActivate(long nativeVrShellDelegate);
    private native void nativeOnPause(long nativeVrShellDelegate);
    private native void nativeOnResume(long nativeVrShellDelegate);
    private native void nativeDestroy(long nativeVrShellDelegate);
    private static native void nativeRegisterVrAssetsComponent();
}
