Ocean
NativeApplication.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_PLATFORM_META_QUEST_OPENXR_APPLICATION_NATIVE_APPLICATION_H
9 #define META_OCEAN_PLATFORM_META_QUEST_OPENXR_APPLICATION_NATIVE_APPLICATION_H
10 
12 
14 
16 
18 
19 #include <openxr/openxr.h>
20 
21 #ifdef OCEAN_PLATFORM_BUILD_ANDROID
22  #include <android/native_window_jni.h>
23  #include <android_native_app_glue.h>
24  #include <android/window.h>
25 #endif
26 
27 namespace Ocean
28 {
29 
30 namespace Platform
31 {
32 
33 namespace Meta
34 {
35 
36 namespace Quest
37 {
38 
39 namespace OpenXR
40 {
41 
42 namespace Application
43 {
44 
45 /**
46  * This class implements a basic OpenXR application for Quest devices based on an Android NativeActivity.
47  * @ingroup platformmetaquestopenxrapplication
48  */
49 class OCEAN_PLATFORM_META_QUEST_OPENXR_APPLICATION_EXPORT NativeApplication
50 {
51  protected:
52 
53  /**
54  * Definition of an unordered map mapping from Android permissions to a counter which is used to delay the announcement of Android permissions;
55  * Positive counter values indicate that the permission has been granted and the counter is used to delay the announcement of the granted permission, cf. `handlePendingAndroidPermissions()` for details.
56  * Negative counter values are used to store the state of a permission.
57  */
58  typedef std::unordered_map<std::string, int> AndroidPermissionMap;
59 
60  /// The counter value for permissions not yet requested.
61  static constexpr int permissionNotYetRequested_ = -2;
62 
63  //// The counter value for permissions not yet granted.
64  static constexpr int permissionNotYetGranted_ = -1;
65 
66  /**
67  * Definition of an unordered set holding strings.
68  */
69  typedef std::unordered_set<std::string> StringSet;
70 
71  /**
72  * Definition of a vector holding XrViewConfigurationView objects.
73  */
74  typedef std::vector<XrViewConfigurationView> XrViewConfigurationViews;
75 
76  public:
77 
78  /**
79  * Destructs this object.
80  */
81  virtual ~NativeApplication();
82 
83  /**
84  * The run method of this application.
85  * Calling this function will start the application logic and will return before the application closes.
86  * True, if the application closes after a successful execution; False, if the application did not start successfully
87  */
88  virtual bool run();
89 
90  /**
91  * Returns the device type that this application is configured for
92  * @return The device type
93  */
94  inline Device::DeviceType deviceType() const;
95 
96  /**
97  * Returns the device name that this application is configured for
98  * @return The device name
99  */
100  inline std::string deviceName() const;
101 
102  /**
103  * Requests an Android permission that needs to be granted by the user.
104  * In case the user grants the permission, the callback function `onPermissionGranted()` will be invoked (when requesting the permission for the first time).
105  * @param permission The name of the Android permission to request, must be valid
106  * @see onPermissionGranted().
107  */
108  void requestAndroidPermission(std::string&& permission);
109 
110  /**
111  * Requests several Android permissions that needs to be granted by the user.
112  * In case the user grants the permission, the callback function `onPermissionGranted()` will be invoked (when requesting the permission for the first time).
113  * @param permissions The names of the Android permissions to request, must be valid
114  * @see onPermissionGranted().
115  */
116  inline void requestAndroidPermissions(std::vector<std::string>&& permissions);
117 
118  /**
119  * Returns the Android permissions which have been granted by the user.
120  * @return The currently granted Android permissions
121  */
123 
124  protected:
125 
126 #ifdef OCEAN_PLATFORM_BUILD_ANDROID
127 
128  /**
129  * Creates a new application object.
130  * @param androidApp The android app object as provided in the main function of the native activity, must be valid
131  */
132  explicit NativeApplication(struct android_app* androidApp);
133 
134 #endif // OCEAN_PLATFORM_BUILD_ANDROID
135 
136  /**
137  * Disabled copy constructor.
138  * @param nativeApplication Application object which would have been copied
139  */
140  NativeApplication(const NativeApplication& nativeApplication) = delete;
141 
142  /**
143  * Returns the names of the necessary OpenXR extensions the application needs.
144  * @return The application's necessary OpenXR extensions
145  */
147 
148  /**
149  * Main loop of the application.
150  */
151  virtual void applicationLoop();
152 
153  /**
154  * Processes all pending Android events via ALooper_pollOnce.
155  */
156  virtual void processAndroidEvents();
157 
158  /**
159  * Processes all pending OpenXR events.
160  */
161  virtual void processOpenXREvents();
162 
163  /**
164  * Event functions for changed reference spaces.
165  * @param xrReferenceSpaceType The type of the reference which has changed
166  * @param previous_T_changed The transformation between the changed space and the previous space, invalid if unknown
167  * @param changeTime The time after which xrLocateSpace or xrLocateViews will return values that respect the change
168  */
169  virtual void onChangedReferenceSpace(const XrReferenceSpaceType xrReferenceSpaceType, const HomogenousMatrix4& previous_T_changed, const XrTime& changeTime);
170 
171  /**
172  * Returns the current state of the OpenXR session.
173  * @return The session's state
174  */
175  inline XrSessionState xrSessionState() const;
176 
177  /**
178  * Creates the OpenXR session.
179  * @param xrViewConfigurationViews The view configuration(s) for the frame buffer(s)
180  * @return True, if succeeded
181  */
182  virtual bool createOpenXRSession(const XrViewConfigurationViews& xrViewConfigurationViews) = 0;
183 
184  /**
185  * Releases the OpenXR session.
186  */
187  virtual void releaseOpenXRSession() = 0;
188 
189  /**
190  * Event function called after OpenXR has been initialized.
191  */
193 
194  /**
195  * Event function called whenever the state of the OpenXR session changed.
196  * @param xrEventDataSessionStateChanged The new OpenXR session state
197  */
198  virtual void onOpenXRSessionChanged(const XrEventDataSessionStateChanged& xrEventDataSessionStateChanged);
199 
200  /**
201  * Event function called whenever the session is ready, when the session state changed to XR_SESSION_STATE_READY.
202  */
203  virtual void onOpenXRSessionReady();
204 
205  /**
206  * Event function called whenever the session is stopping, when the session state changed to XR_SESSION_STATE_STOPPING.
207  */
208  virtual void onOpenXRSessionStopping();
209 
210  /**
211  * Event function call when an Android (or Oculus) permission is granted
212  * @param permission The name of the permission that has been granted
213  */
214  virtual void onAndroidPermissionGranted(const std::string& permission);
215 
216  /**
217  * Event function call when the Android Activity is started.
218  */
219  virtual void onActivityStart();
220 
221  /**
222  * Event function call when the Android Activity is resumed.
223  */
224  virtual void onActivityResume();
225 
226  /**
227  * Event function call when the Android Activity is paused.
228  */
229  virtual void onActivityPause();
230 
231  /**
232  * Event function call when the Android Activity is stopped.
233  */
234  virtual void onActivityStop();
235 
236  /**
237  * Event function call when the Android Activity is destroyed.
238  */
239  virtual void onActivityDestroy();
240 
241  /**
242  * Event function call when the window of the Android Activity is initialized.
243  */
244  virtual void onActivityInitWindow();
245 
246  /**
247  * Event function call when the window of the Android Activity is terminated.
248  */
249  virtual void onActivityTermWindow();
250 
251  /**
252  * Event function called at startup to set e.g., windows flags.
253  */
254  virtual void onStartup();
255 
256  /**
257  * Idle event function called within the main loop whenever all Android related events have been processed.
258  */
259  virtual void onIdle() = 0;
260 
261  /**
262  * Checks if a specific permission has been granted.
263  * @param permission The string identifier of a permission, must be valid
264  * @param translate Optionally translate permissions internally (short to long name), must be `false` in conjunction with Oculus permission such as `com.oculus.permission.USE_SCENE`
265  * @return True if the specified permission has been granted, otherwise false
266  */
267  bool isAndroidPermissionGranted(const std::string& permission, const bool translate = false) const;
268 
269  /**
270  * Checks if any item from a set of pending permissions has been granted to the app
271  * If a pending permission has been found to be granted, it will be removed from the set of pending permissions and added to the set of granted permission.
272  * This will also call `onPermissionGranted()` in order to notify the application about the permission changes.
273  *
274  * Important note:
275  *
276  * In Android, when permissions are granted by the user for the firs time, there seems to be a delay
277  * for some permissions between when (A) they are marked as granted, i.e., `hasPermission()` returns
278  * `true` and (B) when the permission is actually granted and can be used. Any action that requires
279  * such an affected permission that is run in the time between (A) and (B) is still likely to fail (as
280  * if the permission had not been granted in the first place). The permission will be usable after
281  * a few moments (i.e., after a few milliseconds or after a few iterations of the main loop of the app).
282  *
283  * On consecutive starts of the app and assuming all requested permissions have been granted before,
284  * this is no longer a problem; `hasPermission()` returns `true` and the permission is immediately
285  * usable.
286  *
287  * The function applies a short delay before announcing them via `onPermissionGranted()` to all
288  * permissions.
289  *
290  * @param firstCheck True when this function is called for the first time since the app started, otherwise false; cf. the note above.
291  */
292  void handlePendingAndroidPermissions(const bool firstCheck);
293 
294  /**
295  * Disabled copy operator.
296  * @param nativeApplication Application object which would have been copied
297  * @return Reference to this object
298  */
299  NativeApplication& operator=(const NativeApplication& nativeApplication) = delete;
300 
301  /**
302  * Android's command event function.
303  * @param androidApp The android app object
304  * @param cmd The command
305  */
306  static void onAndroidCommand(struct android_app* androidApp, int32_t cmd);
307 
308  protected:
309 
310  /// The OpenXR instance used by this application.
312 
313  /// The OpenXR view configuration type to be used.
314  XrViewConfigurationType xrViewConfigurationType_ = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
315 
316 #ifdef OCEAN_PLATFORM_BUILD_ANDROID
317 
318  /// The Java native interface envrionment.
319  JNIEnv* jniEnv_ = nullptr;
320 
321  // The android app object as provided in the main function of the native activity.
322  struct android_app* androidApp_ = nullptr;
323 
324 #endif
325 
326  /// True, if the application has been resumed; False, if the application has e.g., been paused or stopped.
327  bool applicationResumed_ = false;
328 
329  /// The native Android window, if any.
330  ANativeWindow* androidNativeWindow_ = nullptr;
331 
332  /// The device type that this application is configured for.
334 
335  /// The map mapping the names of pending Android permissions to a delay counter.
337 
338  /// The set holding the names of granted Android permissions.
340 
341  /// The lock for Android permissions.
343 
344  private:
345 
346  /// The current OpenXR session state.
347  XrSessionState xrSessionState_ = XR_SESSION_STATE_UNKNOWN;
348 
349  /// True, if the OpenXR session is ready to be used.
350  bool xrSessionIsReady_ = false;
351 };
352 
354 {
355  return deviceType_;
356 }
357 
358 inline std::string NativeApplication::deviceName() const
359 {
360  return Device::deviceName(deviceType());
361 }
362 
363 inline void NativeApplication::requestAndroidPermissions(std::vector<std::string>&& permissions)
364 {
365  const ScopedLock scopedLock(androidPermissionLock_);
366 
367  for (std::string& permission : permissions)
368  {
369  requestAndroidPermission(std::move(permission));
370  }
371 }
372 
373 inline XrSessionState NativeApplication::xrSessionState() const
374 {
375  return xrSessionState_;
376 }
377 
378 }
379 
380 }
381 
382 }
383 
384 }
385 
386 }
387 
388 }
389 
390 #endif // META_OCEAN_PLATFORM_META_QUEST_OPENXR_APPLICATION_NATIVE_APPLICATION_H
This class implements a recursive lock object.
Definition: Lock.h:31
DeviceType
Definition of individual device types.
Definition: platform/meta/quest/Device.h:37
@ DT_UNKNOWN
Unknown device.
Definition: platform/meta/quest/Device.h:39
static std::string deviceName()
Returns the name of the device.
Definition: platform/meta/quest/Device.h:82
This class implements a basic OpenXR application for Quest devices based on an Android NativeActivity...
Definition: NativeApplication.h:50
virtual void onActivityInitWindow()
Event function call when the window of the Android Activity is initialized.
NativeApplication & operator=(const NativeApplication &nativeApplication)=delete
Disabled copy operator.
Device::DeviceType deviceType() const
Returns the device type that this application is configured for.
Definition: NativeApplication.h:353
void requestAndroidPermission(std::string &&permission)
Requests an Android permission that needs to be granted by the user.
virtual void onActivityStart()
Event function call when the Android Activity is started.
void handlePendingAndroidPermissions(const bool firstCheck)
Checks if any item from a set of pending permissions has been granted to the app If a pending permiss...
virtual void onAndroidPermissionGranted(const std::string &permission)
Event function call when an Android (or Oculus) permission is granted.
virtual void applicationLoop()
Main loop of the application.
std::unordered_map< std::string, int > AndroidPermissionMap
Definition of an unordered map mapping from Android permissions to a counter which is used to delay t...
Definition: NativeApplication.h:58
NativeApplication(struct android_app *androidApp)
Creates a new application object.
virtual void onOpenXRSessionStopping()
Event function called whenever the session is stopping, when the session state changed to XR_SESSION_...
bool isAndroidPermissionGranted(const std::string &permission, const bool translate=false) const
Checks if a specific permission has been granted.
virtual void processOpenXREvents()
Processes all pending OpenXR events.
virtual void onOpenXRInstanceInitialized()
Event function called after OpenXR has been initialized.
virtual void onStartup()
Event function called at startup to set e.g., windows flags.
StringSet grantedAndroidPermissions() const
Returns the Android permissions which have been granted by the user.
virtual void onActivityStop()
Event function call when the Android Activity is stopped.
std::unordered_set< std::string > StringSet
Definition of an unordered set holding strings.
Definition: NativeApplication.h:69
std::vector< XrViewConfigurationView > XrViewConfigurationViews
Definition of a vector holding XrViewConfigurationView objects.
Definition: NativeApplication.h:74
virtual void releaseOpenXRSession()=0
Releases the OpenXR session.
virtual void onIdle()=0
Idle event function called within the main loop whenever all Android related events have been process...
AndroidPermissionMap pendingAndroidPermissionMap_
The map mapping the names of pending Android permissions to a delay counter.
Definition: NativeApplication.h:336
XrSessionState xrSessionState() const
Returns the current state of the OpenXR session.
Definition: NativeApplication.h:373
virtual void onChangedReferenceSpace(const XrReferenceSpaceType xrReferenceSpaceType, const HomogenousMatrix4 &previous_T_changed, const XrTime &changeTime)
Event functions for changed reference spaces.
std::string deviceName() const
Returns the device name that this application is configured for.
Definition: NativeApplication.h:358
virtual void processAndroidEvents()
Processes all pending Android events via ALooper_pollOnce.
virtual void onActivityDestroy()
Event function call when the Android Activity is destroyed.
Platform::OpenXR::Instance xrInstance_
The OpenXR instance used by this application.
Definition: NativeApplication.h:311
virtual bool createOpenXRSession(const XrViewConfigurationViews &xrViewConfigurationViews)=0
Creates the OpenXR session.
virtual void onActivityResume()
Event function call when the Android Activity is resumed.
StringSet grantedAndroidPermissionSet_
The set holding the names of granted Android permissions.
Definition: NativeApplication.h:339
virtual void onActivityTermWindow()
Event function call when the window of the Android Activity is terminated.
virtual StringSet necessaryOpenXRExtensionNames() const
Returns the names of the necessary OpenXR extensions the application needs.
Device::DeviceType deviceType_
The device type that this application is configured for.
Definition: NativeApplication.h:333
virtual void onOpenXRSessionReady()
Event function called whenever the session is ready, when the session state changed to XR_SESSION_STA...
Lock androidPermissionLock_
The lock for Android permissions.
Definition: NativeApplication.h:342
virtual bool run()
The run method of this application.
virtual void onActivityPause()
Event function call when the Android Activity is paused.
virtual void onOpenXRSessionChanged(const XrEventDataSessionStateChanged &xrEventDataSessionStateChanged)
Event function called whenever the state of the OpenXR session changed.
void requestAndroidPermissions(std::vector< std::string > &&permissions)
Requests several Android permissions that needs to be granted by the user.
Definition: NativeApplication.h:363
static void onAndroidCommand(struct android_app *androidApp, int32_t cmd)
Android's command event function.
XrSessionState xrSessionState_
The current OpenXR session state.
Definition: NativeApplication.h:347
NativeApplication(const NativeApplication &nativeApplication)=delete
Disabled copy constructor.
This class wraps an OpenXR instance.
Definition: Instance.h:30
This class implements a scoped lock object for recursive lock objects.
Definition: Lock.h:135
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15