1 package android.app; 2 3 import android.annotation.CallbackExecutor; 4 import android.annotation.NonNull; 5 import android.annotation.Nullable; 6 import android.annotation.RequiresPermission; 7 import android.annotation.SystemApi; 8 import android.annotation.SystemService; 9 import android.compat.annotation.UnsupportedAppUsage; 10 import android.content.ComponentName; 11 import android.content.Context; 12 import android.os.RemoteException; 13 import android.service.vr.IPersistentVrStateCallbacks; 14 import android.service.vr.IVrManager; 15 import android.service.vr.IVrStateCallbacks; 16 import android.util.ArrayMap; 17 import android.view.Display; 18 19 import java.util.Map; 20 import java.util.concurrent.Executor; 21 22 /** 23 * Used to control aspects of a devices Virtual Reality (VR) capabilities. 24 * @hide 25 */ 26 @SystemApi 27 @SystemService(Context.VR_SERVICE) 28 public class VrManager { 29 30 private static class CallbackEntry { 31 final IVrStateCallbacks mStateCallback = new IVrStateCallbacks.Stub() { 32 @Override 33 public void onVrStateChanged(boolean enabled) { 34 mExecutor.execute(() -> mCallback.onVrStateChanged(enabled)); 35 } 36 37 }; 38 final IPersistentVrStateCallbacks mPersistentStateCallback = 39 new IPersistentVrStateCallbacks.Stub() { 40 @Override 41 public void onPersistentVrStateChanged(boolean enabled) { 42 mExecutor.execute(() -> mCallback.onPersistentVrStateChanged(enabled)); 43 } 44 }; 45 final VrStateCallback mCallback; 46 final Executor mExecutor; 47 CallbackEntry(VrStateCallback callback, Executor executor)48 CallbackEntry(VrStateCallback callback, Executor executor) { 49 mCallback = callback; 50 mExecutor = executor; 51 } 52 } 53 54 @UnsupportedAppUsage 55 private final IVrManager mService; 56 private Map<VrStateCallback, CallbackEntry> mCallbackMap = new ArrayMap<>(); 57 58 /** 59 * {@hide} 60 */ VrManager(IVrManager service)61 public VrManager(IVrManager service) { 62 mService = service; 63 } 64 65 /** 66 * Registers a callback to be notified of changes to the VR Mode state. 67 * 68 * @param callback The callback to register. 69 */ 70 @RequiresPermission(anyOf = { 71 android.Manifest.permission.RESTRICTED_VR_ACCESS, 72 android.Manifest.permission.ACCESS_VR_STATE 73 }) registerVrStateCallback(@onNull @allbackExecutor Executor executor, @NonNull VrStateCallback callback)74 public void registerVrStateCallback(@NonNull @CallbackExecutor Executor executor, 75 @NonNull VrStateCallback callback) { 76 if (callback == null || mCallbackMap.containsKey(callback)) { 77 return; 78 } 79 80 CallbackEntry entry = new CallbackEntry(callback, executor); 81 mCallbackMap.put(callback, entry); 82 try { 83 mService.registerListener(entry.mStateCallback); 84 mService.registerPersistentVrStateListener(entry.mPersistentStateCallback); 85 } catch (RemoteException e) { 86 try { 87 unregisterVrStateCallback(callback); 88 } catch (Exception ignore) { 89 e.rethrowFromSystemServer(); 90 } 91 } 92 } 93 94 /** 95 * Deregisters VR State callbacks. 96 * 97 * @param callback The callback to deregister. 98 */ 99 @RequiresPermission(anyOf = { 100 android.Manifest.permission.RESTRICTED_VR_ACCESS, 101 android.Manifest.permission.ACCESS_VR_STATE 102 }) unregisterVrStateCallback(@onNull VrStateCallback callback)103 public void unregisterVrStateCallback(@NonNull VrStateCallback callback) { 104 CallbackEntry entry = mCallbackMap.remove(callback); 105 if (entry != null) { 106 try { 107 mService.unregisterListener(entry.mStateCallback); 108 } catch (RemoteException ignore) { 109 // Dont rethrow exceptions from requests to unregister. 110 } 111 112 try { 113 mService.unregisterPersistentVrStateListener(entry.mPersistentStateCallback); 114 } catch (RemoteException ignore) { 115 // Dont rethrow exceptions from requests to unregister. 116 } 117 } 118 } 119 120 /** 121 * Returns the current VrMode state. 122 */ 123 @RequiresPermission(anyOf = { 124 android.Manifest.permission.RESTRICTED_VR_ACCESS, 125 android.Manifest.permission.ACCESS_VR_STATE 126 }) isVrModeEnabled()127 public boolean isVrModeEnabled() { 128 try { 129 return mService.getVrModeState(); 130 } catch (RemoteException e) { 131 e.rethrowFromSystemServer(); 132 } 133 return false; 134 } 135 136 /** 137 * Returns the current VrMode state. 138 */ 139 @RequiresPermission(anyOf = { 140 android.Manifest.permission.RESTRICTED_VR_ACCESS, 141 android.Manifest.permission.ACCESS_VR_STATE 142 }) isPersistentVrModeEnabled()143 public boolean isPersistentVrModeEnabled() { 144 try { 145 return mService.getPersistentVrModeEnabled(); 146 } catch (RemoteException e) { 147 e.rethrowFromSystemServer(); 148 } 149 return false; 150 } 151 152 /** 153 * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will 154 * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used 155 * by VR viewers to indicate that a device is placed in a VR viewer. 156 * 157 * @see Activity#setVrModeEnabled(boolean, ComponentName) 158 * @param enabled true if the device should be placed in persistent VR mode. 159 */ 160 @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) setPersistentVrModeEnabled(boolean enabled)161 public void setPersistentVrModeEnabled(boolean enabled) { 162 try { 163 mService.setPersistentVrModeEnabled(enabled); 164 } catch (RemoteException e) { 165 e.rethrowFromSystemServer(); 166 } 167 } 168 169 /** 170 * Sets the resolution and DPI of the vr2d virtual display used to display 2D 171 * applications in VR mode. 172 * 173 * @param vr2dDisplayProp properties to be set to the virtual display for 174 * 2D applications in VR mode. 175 * 176 */ 177 @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) setVr2dDisplayProperties( @onNull Vr2dDisplayProperties vr2dDisplayProp)178 public void setVr2dDisplayProperties( 179 @NonNull 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 */ 209 @RequiresPermission(android.Manifest.permission.ACCESS_VR_MANAGER) setStandbyEnabled(boolean standby)210 public void setStandbyEnabled(boolean standby) { 211 try { 212 mService.setStandbyEnabled(standby); 213 } catch (RemoteException e) { 214 e.rethrowFromSystemServer(); 215 } 216 } 217 218 /** 219 * This method is not implemented. 220 * 221 * @param componentName not used 222 */ 223 @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) setVrInputMethod(@ullable ComponentName componentName)224 public void setVrInputMethod(@Nullable ComponentName componentName) { 225 } 226 227 /** 228 * Returns the display id of VR's {@link VirtualDisplay}. 229 * 230 * @see DisplayManager#getDisplay(int) 231 */ 232 @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) getVr2dDisplayId()233 public int getVr2dDisplayId() { 234 try { 235 return mService.getVr2dDisplayId(); 236 } catch (RemoteException e) { 237 e.rethrowFromSystemServer(); 238 } 239 return Display.INVALID_DISPLAY; 240 } 241 } 242