From e6d772330744d2c27545dabfe60a4023495c0925 Mon Sep 17 00:00:00 2001 From: Santos Cordon Date: Tue, 8 Aug 2017 17:11:41 -0700 Subject: Allow VR State Listeners with RESTRICTED_VR_ACCESS permission. Extend the ability to use VrStateListeners to applications that have RESTRICTED_VR_ACCESS permission. Previously, it required ACCESS_VR_MANAGER only. Add VrStateCallback object and methods to VrManager to access the functionality outside of frameworks. Bug: 64360244 Test: Manual. Tested ability from VrCore. Change-Id: I01f1c75b1ccd44a09364df84218168cf6caab322 --- core/java/android/app/VrManager.java | 113 ++++++++++++++++++++- core/java/android/app/VrStateCallback.java | 38 +++++++ core/java/android/service/vr/IVrManager.aidl | 7 ++ core/res/AndroidManifest.xml | 5 + .../com/android/server/vr/VrManagerService.java | 50 +++++++-- 5 files changed, 201 insertions(+), 12 deletions(-) create mode 100644 core/java/android/app/VrStateCallback.java diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java index b40c96c6f0c8..363e20a76a1f 100644 --- a/core/java/android/app/VrManager.java +++ b/core/java/android/app/VrManager.java @@ -1,13 +1,18 @@ package android.app; - +import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; -import android.content.ComponentName; import android.content.Context; +import android.os.Handler; import android.os.RemoteException; +import android.service.vr.IPersistentVrStateCallbacks; import android.service.vr.IVrManager; +import android.service.vr.IVrStateCallbacks; +import android.util.ArrayMap; + +import java.util.Map; /** * Used to control aspects of a devices Virtual Reality (VR) capabilities. @@ -16,7 +21,33 @@ import android.service.vr.IVrManager; @SystemApi @SystemService(Context.VR_SERVICE) public class VrManager { + + private static class CallbackEntry { + final IVrStateCallbacks mStateCallback = new IVrStateCallbacks.Stub() { + @Override + public void onVrStateChanged(boolean enabled) { + mHandler.post(() -> mCallback.onVrStateChanged(enabled)); + } + + }; + final IPersistentVrStateCallbacks mPersistentStateCallback = + new IPersistentVrStateCallbacks.Stub() { + @Override + public void onPersistentVrStateChanged(boolean enabled) { + mHandler.post(() -> mCallback.onPersistentVrStateChanged(enabled)); + } + }; + final VrStateCallback mCallback; + final Handler mHandler; + + CallbackEntry(VrStateCallback callback, Handler handler) { + mCallback = callback; + mHandler = handler; + } + } + private final IVrManager mService; + private Map mCallbackMap = new ArrayMap<>(); /** * {@hide} @@ -25,6 +56,84 @@ public class VrManager { mService = service; } + /** + * Registers a callback to be notified of changes to the VR Mode state. + * + * @param callback The callback to register. + * @hide + */ + @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) + public void registerVrStateCallback(VrStateCallback callback, @NonNull Handler handler) { + if (callback == null || mCallbackMap.containsKey(callback)) { + return; + } + + CallbackEntry entry = new CallbackEntry(callback, handler); + mCallbackMap.put(callback, entry); + try { + mService.registerListener(entry.mStateCallback); + mService.registerPersistentVrStateListener(entry.mPersistentStateCallback); + } catch (RemoteException e) { + try { + unregisterVrStateCallback(callback); + } catch (Exception ignore) { + e.rethrowFromSystemServer(); + } + } + } + + /** + * Deregisters VR State callbacks. + * + * @param callback The callback to deregister. + * @hide + */ + @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) + public void unregisterVrStateCallback(VrStateCallback callback) { + CallbackEntry entry = mCallbackMap.remove(callback); + if (entry != null) { + try { + mService.unregisterListener(entry.mStateCallback); + } catch (RemoteException ignore) { + // Dont rethrow exceptions from requests to unregister. + } + + try { + mService.unregisterPersistentVrStateListener(entry.mPersistentStateCallback); + } catch (RemoteException ignore) { + // Dont rethrow exceptions from requests to unregister. + } + } + } + + /** + * Returns the current VrMode state. + * @hide + */ + @RequiresPermission(android.Manifest.permission.ACCESS_VR_STATE) + public boolean getVrModeEnabled() { + try { + return mService.getVrModeState(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + return false; + } + + /** + * Returns the current VrMode state. + * @hide + */ + @RequiresPermission(android.Manifest.permission.ACCESS_VR_STATE) + public boolean getPersistentVrModeEnabled() { + try { + return mService.getPersistentVrModeEnabled(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + return false; + } + /** * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used diff --git a/core/java/android/app/VrStateCallback.java b/core/java/android/app/VrStateCallback.java new file mode 100644 index 000000000000..742faa06fd1d --- /dev/null +++ b/core/java/android/app/VrStateCallback.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * 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. + */ +package android.app; + +/** + * Listens to VR Mode state changes. Use with methods in {@link VrManager}. + * + * @hide + */ +public abstract class VrStateCallback { + + /** + * Callback triggered when there is a change to Persistent VR State. + * + * @param enabled True when VR State is in persistent mode, false otherwise. + */ + public void onPersistentVrStateChanged(boolean enabled) {} + + /** + * Callback triggered when there is a change to Vr State. + * + * @param enabled True when VR State is in VR mode, false otherwise. + */ + public void onVrStateChanged(boolean enabled) {} +} diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl index 9b37a654ab98..c38fab1f9e2c 100644 --- a/core/java/android/service/vr/IVrManager.aidl +++ b/core/java/android/service/vr/IVrManager.aidl @@ -58,6 +58,13 @@ interface IVrManager { */ boolean getVrModeState(); + /** + * Returns the current Persistent VR mode state. + * + * @return {@code true} if Persistent VR mode is enabled. + */ + boolean getPersistentVrModeEnabled(); + /** * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will * remain in VR mode even if the foreground does not specify VR mode being enabled. Mainly used diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 86c0b436ae29..89bbec2b3bcc 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3512,6 +3512,11 @@ + + +