content: package android.app;
  
  import android.annotation.CallbackExecutor;
  import android.annotation.NonNull;
  import android.annotation.Nullable;
  import android.annotation.RequiresPermission;
  import android.annotation.SystemApi;
  import android.annotation.SystemService;
  import android.annotation.UnsupportedAppUsage;
  import android.content.ComponentName;
  import android.content.Context;
  import android.os.RemoteException;
  import android.service.vr.IPersistentVrStateCallbacks;
  import android.service.vr.IVrManager;
  import android.service.vr.IVrStateCallbacks;
  import android.util.ArrayMap;
  import android.view.Display;
  
  import java.util.Map;
  import java.util.concurrent.Executor;
  
  /**
   * Used to control aspects of a devices Virtual Reality (VR) capabilities.
   * @hide
   */
  @SystemApi
  @SystemService(Context.VR_SERVICE)
  public class VrManager {
  
      private static class CallbackEntry {
          final IVrStateCallbacks mStateCallback = new IVrStateCallbacks.Stub() {
              @Override
              public void onVrStateChanged(boolean enabled) {
                  mExecutor.execute(() -> mCallback.onVrStateChanged(enabled));
              }
  
          };
          final IPersistentVrStateCallbacks mPersistentStateCallback =
                  new IPersistentVrStateCallbacks.Stub() {
              @Override
              public void onPersistentVrStateChanged(boolean enabled) {
                  mExecutor.execute(() -> mCallback.onPersistentVrStateChanged(enabled));
              }
          };
          final VrStateCallback mCallback;
          final Executor mExecutor;
  
          CallbackEntry(VrStateCallback callback, Executor executor) {
              mCallback = callback;
              mExecutor = executor;
          }
      }
  
      @UnsupportedAppUsage
      private final IVrManager mService;
      private Map<VrStateCallback, CallbackEntry> mCallbackMap = new ArrayMap<>();
  
      /**
       * {@hide}
       */
      public VrManager(IVrManager service) {
          mService = service;
      }
  
      /**
       * Registers a callback to be notified of changes to the VR Mode state.
       *
       * @param callback The callback to register.
       */
      @RequiresPermission(anyOf = {
              android.Manifest.permission.RESTRICTED_VR_ACCESS,
              android.Manifest.permission.ACCESS_VR_STATE
      })
      public void registerVrStateCallback(@NonNull @CallbackExecutor Executor executor,
              @NonNull VrStateCallback callback) {
          if (callback == null || mCallbackMap.containsKey(callback)) {
              return;
          }
  
          CallbackEntry entry = new CallbackEntry(callback, executor);
          mCallbackMap.put(callback, entry);
          try {
              mService.registerListener(entry.mStateCallback);
              mService.registerPersistentVrStateListener(entry.mPersistentStateCallback);
          } catch (RemoteException e) {
              try {
                  unregisterVrStateCallback(callback);
              } catch (Exception ignore) {
                  e.rethrowFromSystemServer();
              }
          }
      }
  
      /**
       * Deregisters VR State callbacks.
       *
       * @param callback The callback to deregister.
       */
      @RequiresPermission(anyOf = {
              android.Manifest.permission.RESTRICTED_VR_ACCESS,
              android.Manifest.permission.ACCESS_VR_STATE
      })
      public void unregisterVrStateCallback(@NonNull VrStateCallback callback) {
          CallbackEntry entry = mCallbackMap.remove(callback);
          if (entry != null) {
              try {
                  mService.unregisterListener(entry.mStateCallback);
              } catch (RemoteException ignore) {
                  // Dont rethrow exceptions from requests to unregister.
              }
  
              try {
                  mService.unregisterPersistentVrStateListener(entry.mPersistentStateCallback);
              } catch (RemoteException ignore) {
                  // Dont rethrow exceptions from requests to unregister.
              }
          }
      }
  
      /**
       * Returns the current VrMode state.
       */
      @RequiresPermission(anyOf = {
              android.Manifest.permission.RESTRICTED_VR_ACCESS,
              android.Manifest.permission.ACCESS_VR_STATE
      })
      public boolean isVrModeEnabled() {
          try {
              return mService.getVrModeState();
          } catch (RemoteException e) {
              e.rethrowFromSystemServer();
          }
          return false;
      }
  
      /**
       * Returns the current VrMode state.
       */
      @RequiresPermission(anyOf = {
              android.Manifest.permission.RESTRICTED_VR_ACCESS,
              android.Manifest.permission.ACCESS_VR_STATE
      })
      public boolean isPersistentVrModeEnabled() {
          try {
              return mService.getPersistentVrModeEnabled();
          } catch (RemoteException e) {
              e.rethrowFromSystemServer();
          }
          return false;
      }
  
      /**
       * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will
       * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used
       * by VR viewers to indicate that a device is placed in a VR viewer.
       *
       * @see Activity#setVrModeEnabled(boolean, ComponentName)
       * @param enabled true if the device should be placed in persistent VR mode.
       */
      @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
      public void setPersistentVrModeEnabled(boolean enabled) {
          try {
              mService.setPersistentVrModeEnabled(enabled);
          } catch (RemoteException e) {
              e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Sets the resolution and DPI of the vr2d virtual display used to display 2D
       * applications in VR mode.
       *
       * @param vr2dDisplayProp properties to be set to the virtual display for
       * 2D applications in VR mode.
       *
       */
      @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
      public void setVr2dDisplayProperties(
              @NonNull Vr2dDisplayProperties vr2dDisplayProp) {
          try {
              mService.setVr2dDisplayProperties(vr2dDisplayProp);
          } catch (RemoteException e) {
              e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Set the component name of the compositor service to bind.
       *
       * @param componentName ComponentName of a Service in the application's compositor process to
       * bind to, or null to clear the current binding.
       */
      @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
      public void setAndBindVrCompositor(ComponentName componentName) {
          try {
              mService.setAndBindCompositor(
                      (componentName == null) ? null : componentName.flattenToString());
          } catch (RemoteException e) {
              e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Sets the current standby status of the VR device. Standby mode is only used on standalone vr
       * devices. Standby mode is a deep sleep state where it's appropriate to turn off vr mode.
       *
       * @param standby True if the device is entering standby, false if it's exiting standby.
       */
      @RequiresPermission(android.Manifest.permission.ACCESS_VR_MANAGER)
      public void setStandbyEnabled(boolean standby) {
          try {
              mService.setStandbyEnabled(standby);
          } catch (RemoteException e) {
              e.rethrowFromSystemServer();
          }
      }
  
      /**
       * This method is not implemented.
       *
       * @param componentName not used
       */
      @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
      public void setVrInputMethod(@Nullable ComponentName componentName) {
      }
  
      /**
       * Returns the display id of VR's {@link VirtualDisplay}.
       *
       * @see DisplayManager#getDisplay(int)
       */
      @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
      public int getVr2dDisplayId() {
          try {
              return mService.getVr2dDisplayId();
          } catch (RemoteException e) {
              e.rethrowFromSystemServer();
          }
          return Display.INVALID_DISPLAY;
      }
  }
  