Merge "Allow VR State Listeners with RESTRICTED_VR_ACCESS permission." into oc-mr1-dev

am: 0405d12a31

Change-Id: I8a9c7b921489d12f8b9822d4d2b3b53d17368802
This commit is contained in:
Santos Cordon
2017-08-25 20:18:50 +00:00
committed by android-build-merger
5 changed files with 201 additions and 12 deletions

View File

@@ -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<VrStateCallback, CallbackEntry> 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

View File

@@ -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) {}
}

View File

@@ -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

View File

@@ -3512,6 +3512,11 @@
<permission android:name="android.permission.ACCESS_VR_MANAGER"
android:protectionLevel="signature" />
<!-- Required to access VR-Mode state and state change events via {android.app.VrStateCallback}
@hide -->
<permission android:name="android.permission.ACCESS_VR_STATE"
android:protectionLevel="signature|preinstalled" />
<!-- Allows an application to whitelist tasks during lock task mode
@hide <p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES"

View File

@@ -74,6 +74,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.StringBuilder;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
@@ -414,7 +415,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
@Override
public void registerListener(IVrStateCallbacks cb) {
enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
Manifest.permission.ACCESS_VR_STATE);
if (cb == null) {
throw new IllegalArgumentException("Callback binder object is null.");
}
@@ -424,7 +426,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
@Override
public void unregisterListener(IVrStateCallbacks cb) {
enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
Manifest.permission.ACCESS_VR_STATE);
if (cb == null) {
throw new IllegalArgumentException("Callback binder object is null.");
}
@@ -434,7 +437,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
@Override
public void registerPersistentVrStateListener(IPersistentVrStateCallbacks cb) {
enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
Manifest.permission.ACCESS_VR_STATE);
if (cb == null) {
throw new IllegalArgumentException("Callback binder object is null.");
}
@@ -444,7 +448,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
@Override
public void unregisterPersistentVrStateListener(IPersistentVrStateCallbacks cb) {
enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
Manifest.permission.ACCESS_VR_STATE);
if (cb == null) {
throw new IllegalArgumentException("Callback binder object is null.");
}
@@ -454,19 +459,28 @@ public class VrManagerService extends SystemService implements EnabledComponentC
@Override
public boolean getVrModeState() {
enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
Manifest.permission.ACCESS_VR_STATE);
return VrManagerService.this.getVrMode();
}
@Override
public boolean getPersistentVrModeEnabled() {
enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
Manifest.permission.ACCESS_VR_STATE);
return VrManagerService.this.getPersistentVrMode();
}
@Override
public void setPersistentVrModeEnabled(boolean enabled) {
enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS);
VrManagerService.this.setPersistentVrModeEnabled(enabled);
}
@Override
public void setVr2dDisplayProperties(
Vr2dDisplayProperties vr2dDisplayProp) {
enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS);
VrManagerService.this.setVr2dDisplayProperties(vr2dDisplayProp);
}
@@ -530,11 +544,21 @@ public class VrManagerService extends SystemService implements EnabledComponentC
};
private void enforceCallerPermission(String permission) {
if (mContext.checkCallingOrSelfPermission(permission)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Caller does not hold the permission " + permission);
/**
* Enforces that at lease one of the specified permissions is held by the caller.
* Throws SecurityException if none of the specified permissions are held.
*
* @param permissions One or more permissions to check against.
*/
private void enforceCallerPermissionAnyOf(String... permissions) {
for (String permission : permissions) {
if (mContext.checkCallingOrSelfPermission(permission)
== PackageManager.PERMISSION_GRANTED) {
return;
}
}
throw new SecurityException("Caller does not hold at least one of the permissions: "
+ Arrays.toString(permissions));
}
/**
@@ -1204,4 +1228,10 @@ public class VrManagerService extends SystemService implements EnabledComponentC
return mVrModeEnabled;
}
}
private boolean getPersistentVrMode() {
synchronized (mLock) {
return mPersistentVrModeEnabled;
}
}
}