diff options
| -rw-r--r-- | api/system-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/app/VrManager.java | 17 | ||||
| -rw-r--r-- | core/java/android/service/vr/IVrManager.aidl | 8 | ||||
| -rw-r--r-- | services/core/java/com/android/server/utils/ManagedApplicationService.java | 51 | ||||
| -rw-r--r-- | services/core/java/com/android/server/vr/VrManagerService.java | 40 |
5 files changed, 96 insertions, 21 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index f5015f8a9313..2bc8a929cf4f 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6308,6 +6308,7 @@ package android.app { } public class VrManager { + method public void setAndBindVrCompositor(android.content.ComponentName); method public void setPersistentVrModeEnabled(boolean); } diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java index 578623892a9d..5c6ffa39e6f7 100644 --- a/core/java/android/app/VrManager.java +++ b/core/java/android/app/VrManager.java @@ -4,6 +4,7 @@ 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; @@ -181,4 +182,20 @@ public class VrManager { e.rethrowFromSystemServer(); } } + + /** + * Set the component name of the compositor service to bind. + * + * @param componentName ComponentName of a Service in the application's compositor process to + * bind to, or null to clear the current binding. + */ + @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) + public void setAndBindVrCompositor(ComponentName componentName) { + try { + mService.setAndBindCompositor( + (componentName == null) ? null : componentName.flattenToString()); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl index c38fab1f9e2c..fef92230e7b8 100644 --- a/core/java/android/service/vr/IVrManager.aidl +++ b/core/java/android/service/vr/IVrManager.aidl @@ -93,5 +93,13 @@ interface IVrManager { * currently, else return the display id of the virtual display */ int getVr2dDisplayId(); + + /** + * Set the component name of the compositor service to bind. + * + * @param componentName flattened string representing a ComponentName of a Service in the + * application's compositor process to bind to, or null to clear the current binding. + */ + void setAndBindCompositor(in String componentName); } diff --git a/services/core/java/com/android/server/utils/ManagedApplicationService.java b/services/core/java/com/android/server/utils/ManagedApplicationService.java index 1ea70585aa5f..d965122ee3f3 100644 --- a/services/core/java/com/android/server/utils/ManagedApplicationService.java +++ b/services/core/java/com/android/server/utils/ManagedApplicationService.java @@ -16,6 +16,7 @@ package com.android.server.utils; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; @@ -97,21 +98,23 @@ public class ManagedApplicationService { * @param component the {@link ComponentName} of the application service to bind. * @param userId the user ID of user to bind the application service as. * @param clientLabel the resource ID of a label displayed to the user indicating the - * binding service. + * binding service, or 0 if none is desired. * @param settingsAction an action that can be used to open the Settings UI to enable/disable - * binding to these services. - * @param binderChecker an interface used to validate the returned binder object. + * binding to these services, or null if none is desired. + * @param binderChecker an interface used to validate the returned binder object, or null if + * this interface is unchecked. * @param isImportant bind the user service with BIND_IMPORTANT. * @return a ManagedApplicationService instance. */ public static ManagedApplicationService build(@NonNull final Context context, - @NonNull final ComponentName component, final int userId, @NonNull int clientLabel, - @NonNull String settingsAction, @NonNull BinderChecker binderChecker, - boolean isImportant) { + @NonNull final ComponentName component, final int userId, int clientLabel, + @Nullable String settingsAction, @Nullable BinderChecker binderChecker, + boolean isImportant) { return new ManagedApplicationService(context, component, userId, clientLabel, settingsAction, binderChecker, isImportant); } + /** * @return the user ID of the user that owns the bound service. */ @@ -194,11 +197,14 @@ public class ManagedApplicationService { return; } - final PendingIntent pendingIntent = PendingIntent.getActivity( - mContext, 0, new Intent(mSettingsAction), 0); - final Intent intent = new Intent().setComponent(mComponent). - putExtra(Intent.EXTRA_CLIENT_LABEL, mClientLabel). - putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent); + Intent intent = new Intent().setComponent(mComponent); + if (mClientLabel != 0) { + intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mClientLabel); + } + if (mSettingsAction != null) { + intent.putExtra(Intent.EXTRA_CLIENT_INTENT, + PendingIntent.getActivity(mContext, 0, new Intent(mSettingsAction), 0)); + } final ServiceConnection serviceConnection = new ServiceConnection() { @Override @@ -218,18 +224,21 @@ public class ManagedApplicationService { try { iBinder.linkToDeath(mDeathRecipient, 0); - mBoundInterface = mChecker.asInterface(iBinder); - if (!mChecker.checkType(mBoundInterface)) { - // Received an invalid binder, disconnect - mContext.unbindService(this); - mBoundInterface = null; + mBoundInterface = null; + if (mChecker != null) { + mBoundInterface = mChecker.asInterface(iBinder); + if (!mChecker.checkType(mBoundInterface)) { + // Received an invalid binder, disconnect + mContext.unbindService(this); + mBoundInterface = null; + } + iface = mBoundInterface; + pendingEvent = mPendingEvent; + mPendingEvent = null; } - iface = mBoundInterface; - pendingEvent = mPendingEvent; - mPendingEvent = null; } catch (RemoteException e) { // DOA - Slog.w(TAG, "Unable to bind service: " + intent, e); + Slog.w(TAG, "Unable to bind service: " + componentName, e); mBoundInterface = null; } } @@ -244,7 +253,7 @@ public class ManagedApplicationService { @Override public void onServiceDisconnected(ComponentName componentName) { - Slog.w(TAG, "Service disconnected: " + intent); + Slog.w(TAG, "Service disconnected: " + componentName); mConnection = null; mBoundInterface = null; } diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java index 830ebda0b9c1..5a8de82866f2 100644 --- a/services/core/java/com/android/server/vr/VrManagerService.java +++ b/services/core/java/com/android/server/vr/VrManagerService.java @@ -134,6 +134,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC private int mVrAppProcessId; private EnabledComponentsObserver mComponentObserver; private ManagedApplicationService mCurrentVrService; + private ManagedApplicationService mCurrentVrCompositorService; private ComponentName mDefaultVrService; private Context mContext; private ComponentName mCurrentVrModeComponent; @@ -490,6 +491,13 @@ public class VrManagerService extends SystemService implements EnabledComponentC } @Override + public void setAndBindCompositor(String componentName) { + enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS); + VrManagerService.this.setAndBindCompositor( + (componentName == null) ? null : ComponentName.unflattenFromString(componentName)); + } + + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; @@ -497,6 +505,9 @@ public class VrManagerService extends SystemService implements EnabledComponentC pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed")); pw.println("Persistent VR mode is currently: " + ((mPersistentVrModeEnabled) ? "enabled" : "disabled")); + pw.println("Currently bound VR compositor service: " + + ((mCurrentVrCompositorService == null) + ? "None" : mCurrentVrCompositorService.getComponent())); pw.println("Previous state transitions:\n"); String tab = " "; dumpStateTransitions(pw); @@ -785,6 +796,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC + mCurrentVrService.getComponent() + " for user " + mCurrentVrService.getUserId()); mCurrentVrService.disconnect(); + updateCompositorServiceLocked(UserHandle.USER_NULL, null); mCurrentVrService = null; } else { nothingChanged = true; @@ -798,6 +810,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC Slog.i(TAG, "VR mode component changed to " + component + ", disconnecting " + mCurrentVrService.getComponent() + " for user " + mCurrentVrService.getUserId()); + updateCompositorServiceLocked(UserHandle.USER_NULL, null); createAndConnectService(component, userId); sendUpdatedCaller = true; } else { @@ -1177,6 +1190,33 @@ public class VrManagerService extends SystemService implements EnabledComponentC return INVALID_DISPLAY; } + private void setAndBindCompositor(ComponentName componentName) { + final int userId = UserHandle.getCallingUserId(); + final long token = Binder.clearCallingIdentity(); + synchronized (mLock) { + updateCompositorServiceLocked(userId, componentName); + } + Binder.restoreCallingIdentity(token); + } + + private void updateCompositorServiceLocked(int userId, ComponentName componentName) { + if (mCurrentVrCompositorService != null + && mCurrentVrCompositorService.disconnectIfNotMatching(componentName, userId)) { + // Check if existing service matches the requested one, if not (or if the requested + // component is null) disconnect it. + mCurrentVrCompositorService = null; + } + + if (componentName != null && mCurrentVrCompositorService == null) { + // We don't have an existing service matching the requested component, so attempt to + // connect one. + mCurrentVrCompositorService = ManagedApplicationService.build(mContext, + componentName, userId, /*clientLabel*/0, /*settingsAction*/null, + /*binderChecker*/null, /*isImportant*/true); + mCurrentVrCompositorService.connect(); + } + } + private void setPersistentModeAndNotifyListenersLocked(boolean enabled) { if (mPersistentVrModeEnabled == enabled) { return; |