Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 1 | package android.app; |
| 2 | |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 3 | import android.annotation.CallbackExecutor; |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 4 | import android.annotation.NonNull; |
Jeff Sharkey | d86b8fe | 2017-06-02 17:36:26 -0600 | [diff] [blame] | 5 | import android.annotation.RequiresPermission; |
Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 6 | import android.annotation.SystemApi; |
Jeff Sharkey | d86b8fe | 2017-06-02 17:36:26 -0600 | [diff] [blame] | 7 | import android.annotation.SystemService; |
Tarandeep Singh | 89a6c48 | 2017-11-21 14:26:11 -0800 | [diff] [blame] | 8 | import android.annotation.TestApi; |
Ruben Brunk | 52ea662 | 2017-10-02 23:51:25 -0700 | [diff] [blame] | 9 | import android.content.ComponentName; |
Jeff Sharkey | d86b8fe | 2017-06-02 17:36:26 -0600 | [diff] [blame] | 10 | import android.content.Context; |
Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 11 | import android.os.RemoteException; |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 12 | import android.service.vr.IPersistentVrStateCallbacks; |
Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 13 | import android.service.vr.IVrManager; |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 14 | import android.service.vr.IVrStateCallbacks; |
| 15 | import android.util.ArrayMap; |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 16 | import android.view.Display; |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 17 | |
| 18 | import java.util.Map; |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 19 | import java.util.concurrent.Executor; |
Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 20 | |
| 21 | /** |
| 22 | * Used to control aspects of a devices Virtual Reality (VR) capabilities. |
Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 23 | * @hide |
| 24 | */ |
| 25 | @SystemApi |
Jeff Sharkey | d86b8fe | 2017-06-02 17:36:26 -0600 | [diff] [blame] | 26 | @SystemService(Context.VR_SERVICE) |
Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 27 | public class VrManager { |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 28 | |
| 29 | private static class CallbackEntry { |
| 30 | final IVrStateCallbacks mStateCallback = new IVrStateCallbacks.Stub() { |
| 31 | @Override |
| 32 | public void onVrStateChanged(boolean enabled) { |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 33 | mExecutor.execute(() -> mCallback.onVrStateChanged(enabled)); |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 34 | } |
| 35 | |
| 36 | }; |
| 37 | final IPersistentVrStateCallbacks mPersistentStateCallback = |
| 38 | new IPersistentVrStateCallbacks.Stub() { |
| 39 | @Override |
| 40 | public void onPersistentVrStateChanged(boolean enabled) { |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 41 | mExecutor.execute(() -> mCallback.onPersistentVrStateChanged(enabled)); |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 42 | } |
| 43 | }; |
| 44 | final VrStateCallback mCallback; |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 45 | final Executor mExecutor; |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 46 | |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 47 | CallbackEntry(VrStateCallback callback, Executor executor) { |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 48 | mCallback = callback; |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 49 | mExecutor = executor; |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 50 | } |
| 51 | } |
| 52 | |
Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 53 | private final IVrManager mService; |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 54 | private Map<VrStateCallback, CallbackEntry> mCallbackMap = new ArrayMap<>(); |
Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 55 | |
| 56 | /** |
| 57 | * {@hide} |
| 58 | */ |
| 59 | public VrManager(IVrManager service) { |
| 60 | mService = service; |
| 61 | } |
| 62 | |
| 63 | /** |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 64 | * Registers a callback to be notified of changes to the VR Mode state. |
| 65 | * |
| 66 | * @param callback The callback to register. |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 67 | */ |
Santos Cordon | 01a4ea5 | 2017-08-31 16:36:01 -0700 | [diff] [blame] | 68 | @RequiresPermission(anyOf = { |
| 69 | android.Manifest.permission.RESTRICTED_VR_ACCESS, |
| 70 | android.Manifest.permission.ACCESS_VR_STATE |
| 71 | }) |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 72 | public void registerVrStateCallback(@NonNull @CallbackExecutor Executor executor, |
| 73 | VrStateCallback callback) { |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 74 | if (callback == null || mCallbackMap.containsKey(callback)) { |
| 75 | return; |
| 76 | } |
| 77 | |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 78 | CallbackEntry entry = new CallbackEntry(callback, executor); |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 79 | mCallbackMap.put(callback, entry); |
| 80 | try { |
| 81 | mService.registerListener(entry.mStateCallback); |
| 82 | mService.registerPersistentVrStateListener(entry.mPersistentStateCallback); |
| 83 | } catch (RemoteException e) { |
| 84 | try { |
| 85 | unregisterVrStateCallback(callback); |
| 86 | } catch (Exception ignore) { |
| 87 | e.rethrowFromSystemServer(); |
| 88 | } |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | /** |
| 93 | * Deregisters VR State callbacks. |
| 94 | * |
| 95 | * @param callback The callback to deregister. |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 96 | */ |
Santos Cordon | 01a4ea5 | 2017-08-31 16:36:01 -0700 | [diff] [blame] | 97 | @RequiresPermission(anyOf = { |
| 98 | android.Manifest.permission.RESTRICTED_VR_ACCESS, |
| 99 | android.Manifest.permission.ACCESS_VR_STATE |
| 100 | }) |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 101 | public void unregisterVrStateCallback(VrStateCallback callback) { |
| 102 | CallbackEntry entry = mCallbackMap.remove(callback); |
| 103 | if (entry != null) { |
| 104 | try { |
| 105 | mService.unregisterListener(entry.mStateCallback); |
| 106 | } catch (RemoteException ignore) { |
| 107 | // Dont rethrow exceptions from requests to unregister. |
| 108 | } |
| 109 | |
| 110 | try { |
| 111 | mService.unregisterPersistentVrStateListener(entry.mPersistentStateCallback); |
| 112 | } catch (RemoteException ignore) { |
| 113 | // Dont rethrow exceptions from requests to unregister. |
| 114 | } |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | /** |
| 119 | * Returns the current VrMode state. |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 120 | */ |
Santos Cordon | 01a4ea5 | 2017-08-31 16:36:01 -0700 | [diff] [blame] | 121 | @RequiresPermission(anyOf = { |
| 122 | android.Manifest.permission.RESTRICTED_VR_ACCESS, |
| 123 | android.Manifest.permission.ACCESS_VR_STATE |
| 124 | }) |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 125 | public boolean isVrModeEnabled() { |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 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. |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 136 | */ |
Santos Cordon | 01a4ea5 | 2017-08-31 16:36:01 -0700 | [diff] [blame] | 137 | @RequiresPermission(anyOf = { |
| 138 | android.Manifest.permission.RESTRICTED_VR_ACCESS, |
| 139 | android.Manifest.permission.ACCESS_VR_STATE |
| 140 | }) |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 141 | public boolean isPersistentVrModeEnabled() { |
Santos Cordon | e6d7723 | 2017-08-08 17:11:41 -0700 | [diff] [blame] | 142 | try { |
| 143 | return mService.getPersistentVrModeEnabled(); |
| 144 | } catch (RemoteException e) { |
| 145 | e.rethrowFromSystemServer(); |
| 146 | } |
| 147 | return false; |
| 148 | } |
| 149 | |
| 150 | /** |
Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 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 | * |
Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 155 | * @see Activity#setVrModeEnabled(boolean, ComponentName) |
| 156 | * @param enabled true if the device should be placed in persistent VR mode. |
| 157 | */ |
Jeff Sharkey | d86b8fe | 2017-06-02 17:36:26 -0600 | [diff] [blame] | 158 | @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) |
Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 159 | public void setPersistentVrModeEnabled(boolean enabled) { |
| 160 | try { |
| 161 | mService.setPersistentVrModeEnabled(enabled); |
| 162 | } catch (RemoteException e) { |
| 163 | e.rethrowFromSystemServer(); |
| 164 | } |
| 165 | } |
Kevin Schoedel | 28eae8e | 2017-03-22 11:40:38 -0400 | [diff] [blame] | 166 | |
| 167 | /** |
Karthik Ravi Shankar | 2b9aaed | 2017-05-01 01:34:19 -0700 | [diff] [blame] | 168 | * Sets the resolution and DPI of the vr2d virtual display used to display 2D |
Karthik Ravi Shankar | cdf9ce7 | 2017-04-12 15:31:20 -0700 | [diff] [blame] | 169 | * applications in VR mode. |
| 170 | * |
Karthik Ravi Shankar | 2b9aaed | 2017-05-01 01:34:19 -0700 | [diff] [blame] | 171 | * @param vr2dDisplayProp properties to be set to the virtual display for |
| 172 | * 2D applications in VR mode. |
Karthik Ravi Shankar | cdf9ce7 | 2017-04-12 15:31:20 -0700 | [diff] [blame] | 173 | * |
Karthik Ravi Shankar | cdf9ce7 | 2017-04-12 15:31:20 -0700 | [diff] [blame] | 174 | */ |
Jeff Sharkey | d86b8fe | 2017-06-02 17:36:26 -0600 | [diff] [blame] | 175 | @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) |
Karthik Ravi Shankar | 2b9aaed | 2017-05-01 01:34:19 -0700 | [diff] [blame] | 176 | public void setVr2dDisplayProperties( |
| 177 | Vr2dDisplayProperties vr2dDisplayProp) { |
Karthik Ravi Shankar | cdf9ce7 | 2017-04-12 15:31:20 -0700 | [diff] [blame] | 178 | try { |
Karthik Ravi Shankar | 2b9aaed | 2017-05-01 01:34:19 -0700 | [diff] [blame] | 179 | mService.setVr2dDisplayProperties(vr2dDisplayProp); |
Karthik Ravi Shankar | cdf9ce7 | 2017-04-12 15:31:20 -0700 | [diff] [blame] | 180 | } catch (RemoteException e) { |
| 181 | e.rethrowFromSystemServer(); |
| 182 | } |
| 183 | } |
Ruben Brunk | 52ea662 | 2017-10-02 23:51:25 -0700 | [diff] [blame] | 184 | |
| 185 | /** |
| 186 | * Set the component name of the compositor service to bind. |
| 187 | * |
| 188 | * @param componentName ComponentName of a Service in the application's compositor process to |
| 189 | * bind to, or null to clear the current binding. |
| 190 | */ |
| 191 | @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) |
| 192 | public void setAndBindVrCompositor(ComponentName componentName) { |
| 193 | try { |
| 194 | mService.setAndBindCompositor( |
| 195 | (componentName == null) ? null : componentName.flattenToString()); |
| 196 | } catch (RemoteException e) { |
| 197 | e.rethrowFromSystemServer(); |
| 198 | } |
| 199 | } |
Steven Thomas | 1356ec9 | 2017-09-07 11:26:38 -0700 | [diff] [blame] | 200 | |
| 201 | /** |
| 202 | * Sets the current standby status of the VR device. Standby mode is only used on standalone vr |
| 203 | * devices. Standby mode is a deep sleep state where it's appropriate to turn off vr mode. |
| 204 | * |
| 205 | * @param standby True if the device is entering standby, false if it's exiting standby. |
Steven Thomas | 1356ec9 | 2017-09-07 11:26:38 -0700 | [diff] [blame] | 206 | */ |
| 207 | @RequiresPermission(android.Manifest.permission.ACCESS_VR_MANAGER) |
| 208 | public void setStandbyEnabled(boolean standby) { |
| 209 | try { |
| 210 | mService.setStandbyEnabled(standby); |
| 211 | } catch (RemoteException e) { |
| 212 | e.rethrowFromSystemServer(); |
| 213 | } |
| 214 | } |
Tarandeep Singh | 89a6c48 | 2017-11-21 14:26:11 -0800 | [diff] [blame] | 215 | |
| 216 | /** |
| 217 | * Start VR Input method for the packageName in {@link ComponentName}. |
| 218 | * This method notifies InputMethodManagerService to use VR IME instead of |
| 219 | * regular phone IME. |
| 220 | * @param componentName ComponentName of a VR InputMethod that should be set as selected |
| 221 | * input by InputMethodManagerService. |
Tarandeep Singh | 89a6c48 | 2017-11-21 14:26:11 -0800 | [diff] [blame] | 222 | */ |
| 223 | @TestApi |
| 224 | @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) |
| 225 | public void setVrInputMethod(ComponentName componentName) { |
| 226 | try { |
| 227 | mService.setVrInputMethod(componentName); |
| 228 | } catch (RemoteException e) { |
| 229 | e.rethrowFromSystemServer(); |
| 230 | } |
| 231 | } |
rongliu | 5549266 | 2018-03-21 14:34:58 -0700 | [diff] [blame] | 232 | |
| 233 | /** |
| 234 | * Returns the display id of VR's {@link VirtualDisplay}. |
| 235 | * |
| 236 | * @see DisplayManager#getDisplay(int) |
| 237 | */ |
| 238 | @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) |
| 239 | public int getVr2dDisplayId() { |
| 240 | try { |
| 241 | return mService.getVr2dDisplayId(); |
| 242 | } catch (RemoteException e) { |
| 243 | e.rethrowFromSystemServer(); |
| 244 | } |
| 245 | return Display.INVALID_DISPLAY; |
| 246 | } |
Zak Cohen | 56345f4 | 2017-01-26 13:54:28 -0800 | [diff] [blame] | 247 | } |