1 package android.app; 2 3 import android.annotation.NonNull; 4 import android.annotation.RequiresPermission; 5 import android.annotation.SystemApi; 6 import android.annotation.SystemService; 7 import android.annotation.TestApi; 8 import android.content.ComponentName; 9 import android.content.Context; 10 import android.os.Handler; 11 import android.os.RemoteException; 12 import android.service.vr.IPersistentVrStateCallbacks; 13 import android.service.vr.IVrManager; 14 import android.service.vr.IVrStateCallbacks; 15 import android.util.ArrayMap; 16 17 import java.util.Map; 18 19 /** 20 * Used to control aspects of a devices Virtual Reality (VR) capabilities. 21 * @hide 22 */ 23 @SystemApi 24 @SystemService(Context.VR_SERVICE) 25 public class VrManager { 26 27 private static class CallbackEntry { 28 final IVrStateCallbacks mStateCallback = new IVrStateCallbacks.Stub() { 29 @Override 30 public void onVrStateChanged(boolean enabled) { 31 mHandler.post(() -> mCallback.onVrStateChanged(enabled)); 32 } 33 34 }; 35 final IPersistentVrStateCallbacks mPersistentStateCallback = 36 new IPersistentVrStateCallbacks.Stub() { 37 @Override 38 public void onPersistentVrStateChanged(boolean enabled) { 39 mHandler.post(() -> mCallback.onPersistentVrStateChanged(enabled)); 40 } 41 }; 42 final VrStateCallback mCallback; 43 final Handler mHandler; 44 CallbackEntry(VrStateCallback callback, Handler handler)45 CallbackEntry(VrStateCallback callback, Handler handler) { 46 mCallback = callback; 47 mHandler = handler; 48 } 49 } 50 51 private final IVrManager mService; 52 private Map<VrStateCallback, CallbackEntry> mCallbackMap = new ArrayMap<>(); 53 54 /** 55 * {@hide} 56 */ VrManager(IVrManager service)57 public VrManager(IVrManager service) { 58 mService = service; 59 } 60 61 /** 62 * Registers a callback to be notified of changes to the VR Mode state. 63 * 64 * @param callback The callback to register. 65 * @hide 66 */ 67 @RequiresPermission(anyOf = { 68 android.Manifest.permission.RESTRICTED_VR_ACCESS, 69 android.Manifest.permission.ACCESS_VR_STATE 70 }) registerVrStateCallback(VrStateCallback callback, @NonNull Handler handler)71 public void registerVrStateCallback(VrStateCallback callback, @NonNull Handler handler) { 72 if (callback == null || mCallbackMap.containsKey(callback)) { 73 return; 74 } 75 76 CallbackEntry entry = new CallbackEntry(callback, handler); 77 mCallbackMap.put(callback, entry); 78 try { 79 mService.registerListener(entry.mStateCallback); 80 mService.registerPersistentVrStateListener(entry.mPersistentStateCallback); 81 } catch (RemoteException e) { 82 try { 83 unregisterVrStateCallback(callback); 84 } catch (Exception ignore) { 85 e.rethrowFromSystemServer(); 86 } 87 } 88 } 89 90 /** 91 * Deregisters VR State callbacks. 92 * 93 * @param callback The callback to deregister. 94 * @hide 95 */ 96 @RequiresPermission(anyOf = { 97 android.Manifest.permission.RESTRICTED_VR_ACCESS, 98 android.Manifest.permission.ACCESS_VR_STATE 99 }) unregisterVrStateCallback(VrStateCallback callback)100 public void unregisterVrStateCallback(VrStateCallback callback) { 101 CallbackEntry entry = mCallbackMap.remove(callback); 102 if (entry != null) { 103 try { 104 mService.unregisterListener(entry.mStateCallback); 105 } catch (RemoteException ignore) { 106 // Dont rethrow exceptions from requests to unregister. 107 } 108 109 try { 110 mService.unregisterPersistentVrStateListener(entry.mPersistentStateCallback); 111 } catch (RemoteException ignore) { 112 // Dont rethrow exceptions from requests to unregister. 113 } 114 } 115 } 116 117 /** 118 * Returns the current VrMode state. 119 * @hide 120 */ 121 @RequiresPermission(anyOf = { 122 android.Manifest.permission.RESTRICTED_VR_ACCESS, 123 android.Manifest.permission.ACCESS_VR_STATE 124 }) getVrModeEnabled()125 public boolean getVrModeEnabled() { 126 try { 127 return mService.getVrModeState(); 128 } catch (RemoteException e) { 129 e.rethrowFromSystemServer(); 130 } 131 return false; 132 } 133 134 /** 135 * Returns the current VrMode state. 136 * @hide 137 */ 138 @RequiresPermission(anyOf = { 139 android.Manifest.permission.RESTRICTED_VR_ACCESS, 140 android.Manifest.permission.ACCESS_VR_STATE 141 }) getPersistentVrModeEnabled()142 public boolean getPersistentVrModeEnabled() { 143 try { 144 return mService.getPersistentVrModeEnabled(); 145 } catch (RemoteException e) { 146 e.rethrowFromSystemServer(); 147 } 148 return false; 149 } 150 151 /** 152 * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will 153 * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used 154 * by VR viewers to indicate that a device is placed in a VR viewer. 155 * 156 * @see Activity#setVrModeEnabled(boolean, ComponentName) 157 * @param enabled true if the device should be placed in persistent VR mode. 158 */ 159 @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) setPersistentVrModeEnabled(boolean enabled)160 public void setPersistentVrModeEnabled(boolean enabled) { 161 try { 162 mService.setPersistentVrModeEnabled(enabled); 163 } catch (RemoteException e) { 164 e.rethrowFromSystemServer(); 165 } 166 } 167 168 /** 169 * Sets the resolution and DPI of the vr2d virtual display used to display 2D 170 * applications in VR mode. 171 * 172 * @param vr2dDisplayProp properties to be set to the virtual display for 173 * 2D applications in VR mode. 174 * 175 * {@hide} 176 */ 177 @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) setVr2dDisplayProperties( Vr2dDisplayProperties vr2dDisplayProp)178 public void setVr2dDisplayProperties( 179 Vr2dDisplayProperties vr2dDisplayProp) { 180 try { 181 mService.setVr2dDisplayProperties(vr2dDisplayProp); 182 } catch (RemoteException e) { 183 e.rethrowFromSystemServer(); 184 } 185 } 186 187 /** 188 * Set the component name of the compositor service to bind. 189 * 190 * @param componentName ComponentName of a Service in the application's compositor process to 191 * bind to, or null to clear the current binding. 192 */ 193 @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) setAndBindVrCompositor(ComponentName componentName)194 public void setAndBindVrCompositor(ComponentName componentName) { 195 try { 196 mService.setAndBindCompositor( 197 (componentName == null) ? null : componentName.flattenToString()); 198 } catch (RemoteException e) { 199 e.rethrowFromSystemServer(); 200 } 201 } 202 203 /** 204 * Sets the current standby status of the VR device. Standby mode is only used on standalone vr 205 * devices. Standby mode is a deep sleep state where it's appropriate to turn off vr mode. 206 * 207 * @param standby True if the device is entering standby, false if it's exiting standby. 208 * @hide 209 */ 210 @RequiresPermission(android.Manifest.permission.ACCESS_VR_MANAGER) setStandbyEnabled(boolean standby)211 public void setStandbyEnabled(boolean standby) { 212 try { 213 mService.setStandbyEnabled(standby); 214 } catch (RemoteException e) { 215 e.rethrowFromSystemServer(); 216 } 217 } 218 219 /** 220 * Start VR Input method for the packageName in {@link ComponentName}. 221 * This method notifies InputMethodManagerService to use VR IME instead of 222 * regular phone IME. 223 * @param componentName ComponentName of a VR InputMethod that should be set as selected 224 * input by InputMethodManagerService. 225 * @hide 226 */ 227 @TestApi 228 @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) setVrInputMethod(ComponentName componentName)229 public void setVrInputMethod(ComponentName componentName) { 230 try { 231 mService.setVrInputMethod(componentName); 232 } catch (RemoteException e) { 233 e.rethrowFromSystemServer(); 234 } 235 } 236 } 237