/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * Licensed under the Oculus SDK License Agreement (the "License"); * you may not use the Oculus SDK except in compliance with the License, * which is provided at the time of installation or download, or which * otherwise accompanies this software in either electronic or hard copy form. * * You may obtain a copy of the License at * * https://developer.oculus.com/licenses/oculussdk/ * * Unless required by applicable law or agreed to in writing, the Oculus SDK * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Android; /// /// This class handles Android permission requests for the capabilities listed in . /// /// /// It is recommended to use Unity's Android Permission API directly to request permissions which /// require callbacks. Subscribing to events here may not be guaranteed to be called when /// using startup permissions toggle, due to a potential race /// condition if the request completes before your callback has been registered. /// public static class OVRPermissionsRequester { /// /// Occurs when a is granted. /// public static event Action PermissionGranted; /// /// Enum listing the capabilities this class can request permission for. /// public enum Permission { /// /// Represents the Face Tracking capability. /// FaceTracking, /// /// Represents the Body Tracking capability. /// BodyTracking, /// /// Represents the Eye Tracking capability. /// EyeTracking, /// /// Represents the Scene capability. /// Scene, /// /// Represents the Audio Recording permission (required for audio based Face Tracking capability). /// RecordAudio, } /// /// Android permission string for Face Tracking capability. /// public const string FaceTrackingPermission = "com.oculus.permission.FACE_TRACKING"; /// /// Android permission string for Eye Tracking capability. /// public const string EyeTrackingPermission = "com.oculus.permission.EYE_TRACKING"; /// /// Android permission string for Body Tracking capability. /// public const string BodyTrackingPermission = "com.oculus.permission.BODY_TRACKING"; /// /// Android permission string for Scene (Spatial data) capability. /// public const string ScenePermission = "com.oculus.permission.USE_SCENE"; /// /// Android permission string for Audio Recording. /// public const string RecordAudioPermission = "android.permission.RECORD_AUDIO"; /// /// Returns the permission ID of the given to be requested from the user. /// /// The to get the ID of. /// /// /// See [Permissions on Android](https://developer.android.com/guide/topics/permissions/overview) for general information about /// Android Permissions. /// /// Thrown when an invalid is used. public static string GetPermissionId(Permission permission) { return permission switch { Permission.FaceTracking => FaceTrackingPermission, Permission.BodyTracking => BodyTrackingPermission, Permission.EyeTracking => EyeTrackingPermission, Permission.Scene => ScenePermission, Permission.RecordAudio => RecordAudioPermission, _ => throw new ArgumentOutOfRangeException(nameof(permission), permission, null) }; } private static bool IsPermissionSupportedByPlatform(Permission permission) { return permission switch { Permission.FaceTracking => OVRPlugin.faceTrackingSupported || OVRPlugin.faceTracking2Supported, Permission.BodyTracking => OVRPlugin.bodyTrackingSupported, Permission.EyeTracking => OVRPlugin.eyeTrackingSupported, // Scene is a no-op on unsupported platforms, but the request can always be made Permission.Scene => true, Permission.RecordAudio => true, _ => throw new ArgumentOutOfRangeException(nameof(permission), permission, null) }; } /// /// Returns whether the has been granted. /// /// /// These permissions are Android-specific, therefore we always return /// true if on any other platform. /// /// See [Permissions on Android](https://developer.android.com/guide/topics/permissions/overview) for general information about /// Android Permissions. /// /// to be checked. public static bool IsPermissionGranted(Permission permission) { #if UNITY_ANDROID && !UNITY_EDITOR return UnityEngine.Android.Permission.HasUserAuthorizedPermission(GetPermissionId(permission)); #else return true; #endif } /// /// Requests the listed . /// /// /// See [Permissions on Android](https://developer.android.com/guide/topics/permissions/overview) for general information about /// Android Permissions. /// /// Set of to be requested. public static void Request(IEnumerable permissions) { #if UNITY_ANDROID && !UNITY_EDITOR RequestPermissions(permissions); #endif // UNITY_ANDROID && !UNITY_EDITOR } private static void RequestPermissions(IEnumerable permissions) { var permissionIdsToRequest = new List(); foreach (var permission in permissions) { if (ShouldRequestPermission(permission)) { permissionIdsToRequest.Add(GetPermissionId(permission)); } } if (permissionIdsToRequest.Count > 0) { UnityEngine.Android.Permission.RequestUserPermissions(permissionIdsToRequest.ToArray(), BuildPermissionCallbacks()); } } private static bool ShouldRequestPermission(Permission permission) { if (!IsPermissionSupportedByPlatform(permission)) { Debug.LogWarning( $"[[{nameof(OVRPermissionsRequester)}] Permission {permission} is not supported by the platform and can't be requested."); return false; } return !IsPermissionGranted(permission); } private static PermissionCallbacks BuildPermissionCallbacks() { var permissionCallbacks = new PermissionCallbacks(); permissionCallbacks.PermissionDenied += permissionId => { Debug.LogWarning($"[{nameof(OVRPermissionsRequester)}] Permission {permissionId} was denied."); }; permissionCallbacks.PermissionGranted += permissionId => { Debug.Log($"[{nameof(OVRPermissionsRequester)}] Permission {permissionId} was granted."); PermissionGranted?.Invoke(permissionId); }; // as per Unity guidelines, PermissionDeniedAndDontAskAgain is unreliable // Denied will be fired instead if this isn't subscribed to return permissionCallbacks; } }