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