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