From 16d2397e2d3da0e0fcd6e3d1ea14db4fd5e4e246 Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Fri, 14 Jul 2017 12:32:57 -0400 Subject: [PATCH] Add modified API to send more information to VrCore Currently, null is sent when a 2D intent is running. Sending the component name and a flag instead allows VrCore to determine which intent is currently running and which layers on the display correspond to this application. The process ID of the current intent is also sent, to allow association of buffers to the VR app. Bug: 63709047, 63115025 Test: manual with prints Change-Id: I164b577f2c578867fb953d92074ef3d2d31221a1 --- core/java/android/service/vr/IVrListener.aidl | 2 +- .../android/service/vr/VrListenerService.java | 32 +++++++- .../com/android/server/am/VrController.java | 7 +- .../android/server/vr/VrManagerInternal.java | 3 +- .../android/server/vr/VrManagerService.java | 79 +++++++++++-------- 5 files changed, 84 insertions(+), 39 deletions(-) diff --git a/core/java/android/service/vr/IVrListener.aidl b/core/java/android/service/vr/IVrListener.aidl index afb13d316503d..acca3fa66ae47 100644 --- a/core/java/android/service/vr/IVrListener.aidl +++ b/core/java/android/service/vr/IVrListener.aidl @@ -20,5 +20,5 @@ import android.content.ComponentName; /** @hide */ oneway interface IVrListener { - void focusedActivityChanged(in ComponentName component); + void focusedActivityChanged(in ComponentName component, boolean running2dInVr, int pid); } diff --git a/core/java/android/service/vr/VrListenerService.java b/core/java/android/service/vr/VrListenerService.java index 5da4560f688dd..fa3d065d28a75 100644 --- a/core/java/android/service/vr/VrListenerService.java +++ b/core/java/android/service/vr/VrListenerService.java @@ -70,8 +70,10 @@ public abstract class VrListenerService extends Service { private final IVrListener.Stub mBinder = new IVrListener.Stub() { @Override - public void focusedActivityChanged(ComponentName component) { - mHandler.obtainMessage(MSG_ON_CURRENT_VR_ACTIVITY_CHANGED, component).sendToTarget(); + public void focusedActivityChanged( + ComponentName component, boolean running2dInVr, int pid) { + mHandler.obtainMessage(MSG_ON_CURRENT_VR_ACTIVITY_CHANGED, running2dInVr ? 1 : 0, + pid, component).sendToTarget(); } }; @@ -84,7 +86,8 @@ public abstract class VrListenerService extends Service { public void handleMessage(Message msg) { switch (msg.what) { case MSG_ON_CURRENT_VR_ACTIVITY_CHANGED: { - VrListenerService.this.onCurrentVrActivityChanged((ComponentName) msg.obj); + VrListenerService.this.onCurrentVrActivityChanged( + (ComponentName) msg.obj, msg.arg1 == 1, msg.arg2); } break; } } @@ -119,6 +122,29 @@ public abstract class VrListenerService extends Service { // Override to implement } + /** + * An extended version of onCurrentVrActivityChanged + * + *

This will be called when this service is initially bound, but is not + * guaranteed to be called before onUnbind. In general, this is intended to be used to + * determine when user focus has transitioned between two VR activities, or between a + * VR activity and a 2D activity. This should be overridden instead of the above + * onCurrentVrActivityChanged as that version is deprecated.

+ * + * @param component the {@link ComponentName} of the VR activity or the 2D intent. + * @param running2dInVr true if the component is a 2D component. + * @param pid the process the component is running in. + * + * @see android.app.Activity#setVrModeEnabled + * @see android.R.attr#enableVrMode + * @hide + */ + public void onCurrentVrActivityChanged( + ComponentName component, boolean running2dInVr, int pid) { + // Override to implement. Default to old behaviour of sending null for 2D. + onCurrentVrActivityChanged(running2dInVr ? null : component); + } + /** * Checks if the given component is enabled in user settings. * diff --git a/services/core/java/com/android/server/am/VrController.java b/services/core/java/com/android/server/am/VrController.java index 048bef7b19f5c..feddfe3a21694 100644 --- a/services/core/java/com/android/server/am/VrController.java +++ b/services/core/java/com/android/server/am/VrController.java @@ -163,6 +163,7 @@ final class VrController { ComponentName requestedPackage; ComponentName callingPackage; int userId; + int processId = -1; boolean changed = false; synchronized (mGlobalAmLock) { vrMode = record.requestedVrComponent != null; @@ -172,11 +173,15 @@ final class VrController { // Tell the VrController that a VR mode change is requested. changed = changeVrModeLocked(vrMode, record.app); + + if (record.app != null) { + processId = record.app.pid; + } } // Tell VrManager that a VR mode changed is requested, VrManager will handle // notifying all non-AM dependencies if needed. - vrService.setVrMode(vrMode, requestedPackage, userId, callingPackage); + vrService.setVrMode(vrMode, requestedPackage, userId, processId, callingPackage); return changed; } diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java index 1f7564027166a..bdd9de011186c 100644 --- a/services/core/java/com/android/server/vr/VrManagerInternal.java +++ b/services/core/java/com/android/server/vr/VrManagerInternal.java @@ -52,10 +52,11 @@ public abstract class VrManagerInternal { * @param enabled {@code true} to enable VR mode. * @param packageName The package name of the requested VrListenerService to bind. * @param userId the user requesting the VrListenerService component. + * @param processId the process the component is running in. * @param calling the component currently using VR mode, or null to leave unchanged. */ public abstract void setVrMode(boolean enabled, @NonNull ComponentName packageName, - int userId, @NonNull ComponentName calling); + int userId, int processId, @NonNull ComponentName calling); /** * Set whether the system has acquired a sleep token. diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java index f13cc76577c8c..e73732872cd2a 100644 --- a/services/core/java/com/android/server/vr/VrManagerService.java +++ b/services/core/java/com/android/server/vr/VrManagerService.java @@ -125,6 +125,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC private boolean mVrModeAllowed; private boolean mVrModeEnabled; private boolean mPersistentVrModeEnabled; + private boolean mRunning2dInVr; + private int mVrAppProcessId; private EnabledComponentsObserver mComponentObserver; private ManagedApplicationService mCurrentVrService; private ComponentName mDefaultVrService; @@ -174,7 +176,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC } consumeAndApplyPendingStateLocked(); if (mBootsToVr && !mVrModeEnabled) { - setVrMode(true, mDefaultVrService, 0, null); + setVrMode(true, mDefaultVrService, 0, -1, null); } } else { // Disable persistent mode when VR mode isn't allowed, allows an escape hatch to @@ -183,12 +185,12 @@ public class VrManagerService extends SystemService implements EnabledComponentC // Set pending state to current state. mPendingState = (mVrModeEnabled && mCurrentVrService != null) - ? new VrState(mVrModeEnabled, mCurrentVrService.getComponent(), - mCurrentVrService.getUserId(), mCurrentVrModeComponent) + ? new VrState(mVrModeEnabled, mRunning2dInVr, mCurrentVrService.getComponent(), + mCurrentVrService.getUserId(), mVrAppProcessId, mCurrentVrModeComponent) : null; // Unbind current VR service and do necessary callbacks. - updateCurrentVrServiceLocked(false, null, 0, null); + updateCurrentVrServiceLocked(false, false, null, 0, -1, null); } } } @@ -270,26 +272,33 @@ public class VrManagerService extends SystemService implements EnabledComponentC private static class VrState { final boolean enabled; + final boolean running2dInVr; final int userId; + final int processId; final ComponentName targetPackageName; final ComponentName callingPackage; final long timestamp; final boolean defaultPermissionsGranted; - VrState(boolean enabled, ComponentName targetPackageName, int userId, - ComponentName callingPackage) { + + VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId, + int processId, ComponentName callingPackage) { this.enabled = enabled; + this.running2dInVr = running2dInVr; this.userId = userId; + this.processId = processId; this.targetPackageName = targetPackageName; this.callingPackage = callingPackage; this.defaultPermissionsGranted = false; this.timestamp = System.currentTimeMillis(); } - VrState(boolean enabled, ComponentName targetPackageName, int userId, - ComponentName callingPackage, boolean defaultPermissionsGranted) { + VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId, + int processId, ComponentName callingPackage, boolean defaultPermissionsGranted) { this.enabled = enabled; + this.running2dInVr = running2dInVr; this.userId = userId; + this.processId = processId; this.targetPackageName = targetPackageName; this.callingPackage = callingPackage; this.defaultPermissionsGranted = defaultPermissionsGranted; @@ -390,8 +399,9 @@ public class VrManagerService extends SystemService implements EnabledComponentC } // There is an active service, update it if needed - updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(), - mCurrentVrService.getUserId(), mCurrentVrModeComponent); + updateCurrentVrServiceLocked(mVrModeEnabled, mRunning2dInVr, + mCurrentVrService.getComponent(), mCurrentVrService.getUserId(), + mVrAppProcessId, mCurrentVrModeComponent); } } @@ -527,9 +537,9 @@ public class VrManagerService extends SystemService implements EnabledComponentC */ private final class LocalService extends VrManagerInternal { @Override - public void setVrMode(boolean enabled, ComponentName packageName, int userId, + public void setVrMode(boolean enabled, ComponentName packageName, int userId, int processId, ComponentName callingPackage) { - VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage); + VrManagerService.this.setVrMode(enabled, packageName, userId, processId, callingPackage); } @Override @@ -704,14 +714,16 @@ public class VrManagerService extends SystemService implements EnabledComponentC * Note: Must be called while holding {@code mLock}. * * @param enabled new state for VR mode. + * @param running2dInVr true if we have a top-level 2D intent. * @param component new component to be bound as a VR listener. * @param userId user owning the component to be bound. - * @param calling the component currently using VR mode. + * @param processId the process hosting the activity specified by calling. + * @param calling the component currently using VR mode or a 2D intent. * * @return {@code true} if the component/user combination specified is valid. */ - private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component, - int userId, ComponentName calling) { + private boolean updateCurrentVrServiceLocked(boolean enabled, boolean running2dInVr, + @NonNull ComponentName component, int userId, int processId, ComponentName calling) { boolean sendUpdatedCaller = false; final long identity = Binder.clearCallingIdentity(); @@ -771,6 +783,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC sendUpdatedCaller = true; } mCurrentVrModeComponent = calling; + mRunning2dInVr = running2dInVr; + mVrAppProcessId = processId; if (mCurrentVrModeUser != userId) { mCurrentVrModeUser = userId; @@ -788,11 +802,13 @@ public class VrManagerService extends SystemService implements EnabledComponentC if (mCurrentVrService != null && sendUpdatedCaller) { final ComponentName c = mCurrentVrModeComponent; + final boolean b = running2dInVr; + final int pid = processId; mCurrentVrService.sendEvent(new PendingEvent() { @Override public void runEvent(IInterface service) throws RemoteException { IVrListener l = (IVrListener) service; - l.focusedActivityChanged(c); + l.focusedActivityChanged(c, b, pid); } }); } @@ -1017,20 +1033,20 @@ public class VrManagerService extends SystemService implements EnabledComponentC */ private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) { if (mPendingState != null) { - updateCurrentVrServiceLocked(mPendingState.enabled, - mPendingState.targetPackageName, mPendingState.userId, + updateCurrentVrServiceLocked(mPendingState.enabled, mPendingState.running2dInVr, + mPendingState.targetPackageName, mPendingState.userId, mPendingState.processId, mPendingState.callingPackage); mPendingState = null; } else if (disconnectIfNoPendingState) { - updateCurrentVrServiceLocked(false, null, 0, null); + updateCurrentVrServiceLocked(false, false, null, 0, -1, null); } } private void logStateLocked() { ComponentName currentBoundService = (mCurrentVrService == null) ? null : mCurrentVrService.getComponent(); - VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser, - mCurrentVrModeComponent, mWasDefaultGranted); + VrState current = new VrState(mVrModeEnabled, mRunning2dInVr, currentBoundService, + mCurrentVrModeUser, mVrAppProcessId, mCurrentVrModeComponent, mWasDefaultGranted); if (mLoggingDeque.size() == EVENT_LOG_SIZE) { mLoggingDeque.removeFirst(); } @@ -1074,27 +1090,24 @@ public class VrManagerService extends SystemService implements EnabledComponentC * Implementation of VrManagerInternal calls. These are callable from system services. */ private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName, - int userId, @NonNull ComponentName callingPackage) { + int userId, int processId, @NonNull ComponentName callingPackage) { synchronized (mLock) { VrState pending; ComponentName targetListener; - ComponentName foregroundVrComponent; // If the device is in persistent VR mode, then calls to disable VR mode are ignored, // and the system default VR listener is used. boolean targetEnabledState = enabled || mPersistentVrModeEnabled; - if (!enabled && mPersistentVrModeEnabled) { + boolean running2dInVr = !enabled && mPersistentVrModeEnabled; + if (running2dInVr) { targetListener = mDefaultVrService; - - // Current foreground component isn't a VR one (in 2D app case) - foregroundVrComponent = null; } else { targetListener = targetPackageName; - foregroundVrComponent = callingPackage; } - pending = new VrState( - targetEnabledState, targetListener, userId, foregroundVrComponent); + + pending = new VrState(targetEnabledState, running2dInVr, targetListener, + userId, processId, callingPackage); if (!mVrModeAllowed) { // We're not allowed to be in VR mode. Make this state pending. This will be @@ -1119,8 +1132,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC mPendingState = null; } - updateCurrentVrServiceLocked( - targetEnabledState, targetListener, userId, foregroundVrComponent); + updateCurrentVrServiceLocked(targetEnabledState, running2dInVr, targetListener, + userId, processId, callingPackage); } } @@ -1129,7 +1142,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC setPersistentModeAndNotifyListenersLocked(enabled); // Disabling persistent mode when not showing a VR should disable the overall vr mode. if (!enabled && mCurrentVrModeComponent == null) { - setVrMode(false, null, 0, null); + setVrMode(false, null, 0, -1, null); } } }