From c7be3beced4ade05466a4a77c003ea81c2429f74 Mon Sep 17 00:00:00 2001
From: Ruben Brunk
Date: Fri, 1 Apr 2016 17:07:51 -0700
Subject: [PATCH] Add VrManager AIDL interface for use by system apps.
Bug: 27884853
Change-Id: I6de0d291deafe5003070d60866c60d6599312e79
---
Android.mk | 2 +
core/java/android/service/vr/IVrManager.aidl | 46 ++++++++
.../java/android/service/vr/IVrStateCallbacks.aidl | 24 +++++
core/res/AndroidManifest.xml | 5 +
.../com/android/server/lights/LightsService.java | 17 ++-
.../android/server/power/PowerManagerService.java | 13 ++-
.../com/android/server/vr/VrManagerInternal.java | 23 ----
.../com/android/server/vr/VrManagerService.java | 117 +++++++++++++++------
8 files changed, 188 insertions(+), 59 deletions(-)
create mode 100644 core/java/android/service/vr/IVrManager.aidl
create mode 100644 core/java/android/service/vr/IVrStateCallbacks.aidl
diff --git a/Android.mk b/Android.mk
index fc9c319a996a..ae5d67ed2de3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -244,6 +244,8 @@ LOCAL_SRC_FILES += \
core/java/android/service/notification/IConditionListener.aidl \
core/java/android/service/notification/IConditionProvider.aidl \
core/java/android/service/vr/IVrListener.aidl \
+ core/java/android/service/vr/IVrManager.aidl \
+ core/java/android/service/vr/IVrStateCallbacks.aidl \
core/java/android/print/ILayoutResultCallback.aidl \
core/java/android/print/IPrinterDiscoveryObserver.aidl \
core/java/android/print/IPrintDocumentAdapter.aidl \
diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl
new file mode 100644
index 000000000000..62ecab3583cd
--- /dev/null
+++ b/core/java/android/service/vr/IVrManager.aidl
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2016, 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.service.vr;
+
+import android.service.vr.IVrStateCallbacks;
+
+/** @hide */
+interface IVrManager {
+
+ /**
+ * Add a callback to be notified when VR mode state changes.
+ *
+ * @param cb the callback instance to add.
+ */
+ void registerListener(in IVrStateCallbacks cb);
+
+ /**
+ * Remove the callack from the current set of registered callbacks.
+ *
+ * @param cb the callback to remove.
+ */
+ void unregisterListener(in IVrStateCallbacks cb);
+
+ /**
+ * Return current VR mode state.
+ *
+ * @return {@code true} if VR mode is enabled.
+ */
+ boolean getVrModeState();
+
+}
+
diff --git a/core/java/android/service/vr/IVrStateCallbacks.aidl b/core/java/android/service/vr/IVrStateCallbacks.aidl
new file mode 100644
index 000000000000..c4fdcd071fe5
--- /dev/null
+++ b/core/java/android/service/vr/IVrStateCallbacks.aidl
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2016, 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.service.vr;
+
+/** @hide */
+oneway interface IVrStateCallbacks {
+
+ void onVrStateChanged(in boolean enabled);
+
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9219e81fb69b..af8158556255 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2991,6 +2991,11 @@
+
+
+
- * This listener will immediately be called with the current VR mode state.
- *
- * @param listener the listener instance to add.
- */
- public abstract void registerListener(@NonNull VrStateListener listener);
-
- /**
- * Remove the listener from the current set of listeners.
- *
- * @param listener the listener to remove.
- */
- public abstract void unregisterListener(@NonNull VrStateListener listener);
-
/**
* Return NO_ERROR if the given package is installed on the device and enabled as a
* VrListenerService for the given current user, or a negative error code indicating a failure.
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index c572e766f1ec..e6e5a2db0725 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -15,6 +15,7 @@
*/
package com.android.server.vr;
+import android.Manifest;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.annotation.NonNull;
@@ -29,11 +30,15 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.vr.IVrListener;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
import android.service.vr.VrListenerService;
import android.util.ArraySet;
import android.util.Slog;
@@ -46,6 +51,7 @@ import com.android.server.utils.ManagedApplicationService;
import com.android.server.utils.ManagedApplicationService.BinderChecker;
import java.lang.StringBuilder;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
@@ -75,6 +81,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
public static final String TAG = "VrManagerService";
+ public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager";
+
private static native void initializeNative();
private static native void setVrModeNative(boolean enabled);
@@ -84,7 +92,6 @@ public class VrManagerService extends SystemService implements EnabledComponentC
// State protected by mLock
private boolean mVrModeEnabled;
- private final Set mListeners = new ArraySet<>();
private EnabledComponentsObserver mComponentObserver;
private ManagedApplicationService mCurrentVrService;
private Context mContext;
@@ -92,10 +99,37 @@ public class VrManagerService extends SystemService implements EnabledComponentC
private int mCurrentVrModeUser;
private boolean mWasDefaultGranted;
private boolean mGuard;
+ private final RemoteCallbackList mRemoteCallbacks =
+ new RemoteCallbackList<>();
private final ArraySet mPreviousToggledListenerSettings = new ArraySet<>();
private String mPreviousNotificationPolicyAccessPackage;
private String mPreviousManageOverlayPackage;
+ private static final int MSG_VR_STATE_CHANGE = 0;
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case MSG_VR_STATE_CHANGE : {
+ boolean state = (msg.arg1 == 1);
+ int i = mRemoteCallbacks.beginBroadcast();
+ while (i > 0) {
+ i--;
+ try {
+ mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
+ } catch (RemoteException e) {
+ // Noop
+ }
+ }
+ mRemoteCallbacks.finishBroadcast();
+ } break;
+ default :
+ throw new IllegalStateException("Unknown message type: " + msg.what);
+ }
+ }
+ };
+
private static final BinderChecker sBinderChecker = new BinderChecker() {
@Override
public IInterface asInterface(IBinder binder) {
@@ -125,34 +159,55 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
}
- /**
- * Implementation of VrManagerInternal. Callable only from system services.
- */
- private final class LocalService extends VrManagerInternal {
+ private final IVrManager mVrManager = new IVrManager.Stub() {
+
@Override
- public boolean isInVrMode() {
- return VrManagerService.this.getVrMode();
+ public void registerListener(IVrStateCallbacks cb) {
+ enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
+ if (cb == null) {
+ throw new IllegalArgumentException("Callback binder object is null.");
+ }
+
+ VrManagerService.this.addStateCallback(cb);
}
@Override
- public void setVrMode(boolean enabled, ComponentName packageName, int userId,
- ComponentName callingPackage) {
- VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
+ public void unregisterListener(IVrStateCallbacks cb) {
+ enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
+ if (cb == null) {
+ throw new IllegalArgumentException("Callback binder object is null.");
+ }
+
+ VrManagerService.this.removeStateCallback(cb);
}
@Override
- public boolean isCurrentVrListener(String packageName, int userId) {
- return VrManagerService.this.isCurrentVrListener(packageName, userId);
+ public boolean getVrModeState() {
+ return VrManagerService.this.getVrMode();
+ }
+
+ };
+
+ private void enforceCallerPermission(String permission) {
+ if (mContext.checkCallingOrSelfPermission(permission)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller does not hold the permission " + permission);
}
+ }
+ /**
+ * Implementation of VrManagerInternal. Callable only from system services.
+ */
+ private final class LocalService extends VrManagerInternal {
@Override
- public void registerListener(VrStateListener listener) {
- VrManagerService.this.addListener(listener);
+ public void setVrMode(boolean enabled, ComponentName packageName, int userId,
+ ComponentName callingPackage) {
+ VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
}
@Override
- public void unregisterListener(VrStateListener listener) {
- VrManagerService.this.removeListener(listener);
+ public boolean isCurrentVrListener(String packageName, int userId) {
+ return VrManagerService.this.isCurrentVrListener(packageName, userId);
}
@Override
@@ -173,6 +228,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
publishLocalService(VrManagerInternal.class, new LocalService());
+ publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder());
}
@Override
@@ -551,9 +607,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
* Note: Must be called while holding {@code mLock}.
*/
private void onVrModeChangedLocked() {
- for (VrStateListener l : mListeners) {
- l.onVrStateChanged(mVrModeEnabled);
- }
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
+ (mVrModeEnabled) ? 1 : 0, 0));
}
/**
@@ -577,9 +632,9 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
}
- private boolean getVrMode() {
+ private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
synchronized (mLock) {
- return mVrModeEnabled;
+ return mComponentObserver.isValid(targetPackageName, userId);
}
}
@@ -593,21 +648,21 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
}
- private void addListener(VrStateListener listener) {
- synchronized (mLock) {
- mListeners.add(listener);
- }
+ /*
+ * Implementation of IVrManager calls.
+ */
+
+ private void addStateCallback(IVrStateCallbacks cb) {
+ mRemoteCallbacks.register(cb);
}
- private void removeListener(VrStateListener listener) {
- synchronized (mLock) {
- mListeners.remove(listener);
- }
+ private void removeStateCallback(IVrStateCallbacks cb) {
+ mRemoteCallbacks.unregister(cb);
}
- private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
+ private boolean getVrMode() {
synchronized (mLock) {
- return mComponentObserver.isValid(targetPackageName, userId);
+ return mVrModeEnabled;
}
}
}
--
2.11.0