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