OSDN Git Service

Launch 2D activities in VR mode
authorKarthik Ravi Shankar <karthikrs@google.com>
Thu, 9 Mar 2017 02:30:19 +0000 (18:30 -0800)
committerKarthik Ravi Shankar <karthikrs@google.com>
Fri, 31 Mar 2017 15:37:05 +0000 (08:37 -0700)
When in VR mode, launch all activities into the virtual display ID as
provided by the Compatibility display. This includes two cases -

- New activity launches
- Existing activity in the background.

Testing Done: Tested with PlanarVirtualDisplay app and Settings,
Calculator and GestureApp with different intent flags.

Bug: 36071574
Bug: 36071445
Test: android.server.cts.ActivityManagerDisplayTests
Test: #testVrActivityLaunch
Test: #testVrActivityReLaunch

Change-Id: Ic590a7cbd6f9b339dc83b22a8ffb1252219ef22e
Signed-off-by: Karthik Ravi Shankar <karthikrs@google.com>
core/java/android/app/ActivityManagerInternal.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/ActivityStarter.java
services/core/java/com/android/server/vr/CompatibilityDisplay.java
services/core/java/com/android/server/vr/VrManagerService.java

index dbcdecc..65cb5f4 100644 (file)
@@ -241,4 +241,11 @@ public abstract class ActivityManagerInternal {
      * {@param procStateSeq}.
      */
     public abstract void notifyNetworkPolicyRulesUpdated(int uid, long procStateSeq);
+
+    /**
+     * Called after virtual display Id is updated by
+     * {@link com.android.server.vr.CompatibilityDisplay} with a specific
+     * {@param compatibilityDisplayId}.
+     */
+    public abstract void setVrCompatibilityDisplayId(int vrCompatibilityDisplayId);
 }
index ead1b26..f5d9c1c 100644 (file)
@@ -59,6 +59,7 @@ import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
 import static android.provider.Settings.System.FONT_SCALE;
 import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
 import static com.android.internal.util.XmlUtils.readBooleanAttribute;
 import static com.android.internal.util.XmlUtils.readIntAttribute;
 import static com.android.internal.util.XmlUtils.readLongAttribute;
@@ -689,6 +690,9 @@ public class ActivityManagerService extends IActivityManager.Stub
         }
     };
 
+    // VR Compatibility Display Id.
+    int mVrCompatibilityDisplayId = INVALID_DISPLAY;
+
     // Whether we should use SCHED_FIFO for UI and RenderThreads.
     private boolean mUseFifoUiScheduling = false;
 
@@ -23526,6 +23530,22 @@ public class ActivityManagerService extends IActivityManager.Stub
                 }
             }
         }
+
+        /**
+         * Called after virtual display Id is updated by
+         * {@link com.android.server.vr.CompatibilityDisplay} with a specific
+         * {@param vrCompatibilityDisplayId}.
+         */
+        @Override
+        public void setVrCompatibilityDisplayId(int vrCompatibilityDisplayId) {
+            if (DEBUG_STACK) {
+                Slog.d(TAG, "setVrCompatibilityDisplayId called for: " +
+                        vrCompatibilityDisplayId);
+            }
+            synchronized (ActivityManagerService.this) {
+                mVrCompatibilityDisplayId = vrCompatibilityDisplayId;
+            }
+        }
     }
 
     /**
index 9258539..68036f3 100644 (file)
@@ -125,8 +125,10 @@ import android.view.Display;
 
 import com.android.internal.app.HeavyWeightSwitcherActivity;
 import com.android.internal.app.IVoiceInteractor;
+import com.android.server.LocalServices;
 import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
 import com.android.server.pm.InstantAppResolver;
+import com.android.server.vr.VrManagerInternal;
 import com.android.server.wm.WindowManagerService;
 
 import java.util.ArrayList;
@@ -192,6 +194,8 @@ class ActivityStarter {
     private IVoiceInteractionSession mVoiceSession;
     private IVoiceInteractor mVoiceInteractor;
 
+    private boolean mUsingVrCompatibilityDisplay;
+
     private void reset() {
         mStartActivity = null;
         mIntent = null;
@@ -229,12 +233,15 @@ class ActivityStarter {
 
         mVoiceSession = null;
         mVoiceInteractor = null;
+
+        mUsingVrCompatibilityDisplay = false;
     }
 
     ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
         mService = service;
         mSupervisor = supervisor;
         mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
+        mUsingVrCompatibilityDisplay = false;
     }
 
     final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
@@ -1208,10 +1215,7 @@ class ActivityStarter {
         mVoiceSession = voiceSession;
         mVoiceInteractor = voiceInteractor;
 
-        mSourceDisplayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
-        if (mSourceDisplayId == INVALID_DISPLAY) {
-            mSourceDisplayId = DEFAULT_DISPLAY;
-        }
+        mSourceDisplayId = getSourceDisplayId(mSourceRecord, mStartActivity);
 
         mLaunchBounds = getOverrideBounds(r, options, inTask);
 
@@ -1466,6 +1470,36 @@ class ActivityStarter {
     }
 
     /**
+     * Returns the ID of the display to use for a new activity. If the source activity has
+     * a explicit display ID set, use that to launch the activity. If not and the device is in VR
+     * mode, then return the Vr mode's virtual display ID.
+     */
+    private int getSourceDisplayId(ActivityRecord sourceRecord, ActivityRecord startingActivity) {
+        int displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
+        // If the activity has a displayId set explicitly, launch it on the same displayId.
+        if (displayId != INVALID_DISPLAY) {
+            return displayId;
+        }
+
+        // Check if the Activity is a VR activity. If so, the activity should be launched in
+        // main display.
+        if (startingActivity != null && startingActivity.requestedVrComponent != null) {
+            return DEFAULT_DISPLAY;
+        }
+
+        // Get the virtual display id from ActivityManagerService.
+        displayId = mService.mVrCompatibilityDisplayId;
+        if (displayId != INVALID_DISPLAY) {
+            if (DEBUG_STACK) {
+                Slog.d(TAG, "getSourceDisplayId :" + displayId);
+            }
+            mUsingVrCompatibilityDisplay = true;
+            return displayId;
+        }
+        return DEFAULT_DISPLAY;
+    }
+
+    /**
      * Figure out which task and activity to bring to front when we have found an existing matching
      * activity record in history. May also clear the task if needed.
      * @param intentActivity Existing matching activity.
@@ -2073,8 +2107,18 @@ class ActivityStarter {
             return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
         }
 
-        if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0
-                || mSourceDisplayId != DEFAULT_DISPLAY) {
+        // If we are using Vr compatibility display, find the virtual display stack.
+        if (mUsingVrCompatibilityDisplay) {
+            ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
+            if (DEBUG_STACK) {
+                Slog.v(TAG, "Launch stack for app: " + r.toString() +
+                    ", on virtual display stack:" + as.toString());
+            }
+            return as;
+        }
+
+        if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
+                 || mSourceDisplayId != DEFAULT_DISPLAY) {
             return null;
         }
         // Otherwise handle adjacent launch.
index a8d6223..ae1d50f 100644 (file)
@@ -2,6 +2,7 @@ package com.android.server.vr;
 
 import static android.view.Display.INVALID_DISPLAY;
 
+import android.app.ActivityManagerInternal;
 import android.app.Service;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -48,6 +49,7 @@ class CompatibilityDisplay {
     private final static String DEBUG_EXTRA_SURFACE =
             "com.android.server.vr.CompatibilityDisplay.EXTRA_SURFACE";
 
+    private final ActivityManagerInternal mActivityManagerInternal;
     private final DisplayManager mDisplayManager;
     private final IVrManager mVrManager;
     private final Object mVdLock = new Object();
@@ -74,8 +76,10 @@ class CompatibilityDisplay {
     private boolean mIsVrModeOverrideEnabled;
     private boolean mIsVrModeEnabled;
 
-    public CompatibilityDisplay(DisplayManager displayManager, IVrManager vrManager) {
+    public CompatibilityDisplay(DisplayManager displayManager,
+           ActivityManagerInternal activityManagerInternal, IVrManager vrManager) {
         mDisplayManager = displayManager;
+        mActivityManagerInternal = activityManagerInternal;
         mVrManager = vrManager;
     }
 
@@ -200,6 +204,15 @@ class CompatibilityDisplay {
 
             mVirtualDisplay = mDisplayManager.createVirtualDisplay("VR 2D Display", WIDTH, HEIGHT,
                     DPI, null /* Surface */, 0 /* flags */);
+
+            if (mVirtualDisplay != null) {
+                mActivityManagerInternal.setVrCompatibilityDisplayId(
+                    mVirtualDisplay.getDisplay().getDisplayId());
+            } else {
+                Log.w(TAG, "Virtual display id is null after createVirtualDisplay");
+                mActivityManagerInternal.setVrCompatibilityDisplayId(INVALID_DISPLAY);
+                return;
+            }
         }
 
         if (DEBUG) {
@@ -222,6 +235,7 @@ class CompatibilityDisplay {
                     } else {
                         Log.i(TAG, "Stopping Virtual Display");
                         synchronized (mVdLock) {
+                            mActivityManagerInternal.setVrCompatibilityDisplayId(INVALID_DISPLAY);
                             setSurfaceLocked(null); // clean up and release the surface first.
                             if (mVirtualDisplay != null) {
                                 mVirtualDisplay.release();
index 731f53f..324faff 100644 (file)
@@ -18,6 +18,7 @@ package com.android.server.vr;
 import static android.view.Display.INVALID_DISPLAY;
 
 import android.Manifest;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.NotificationManager;
@@ -54,6 +55,7 @@ import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.R;
+import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
 import com.android.server.SystemService;
 import com.android.server.utils.ManagedApplicationService.PendingEvent;
@@ -594,7 +596,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
 
             DisplayManager dm =
                     (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
-            mCompatibilityDisplay = new CompatibilityDisplay(dm, mVrManager);
+            ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
+            mCompatibilityDisplay = new CompatibilityDisplay(dm, ami, mVrManager);
             mCompatibilityDisplay.init(getContext());
         } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
             synchronized (mLock) {