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