Launch 2D activities in VR mode
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>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1465,6 +1469,36 @@ class ActivityStarter {
|
||||
return intentActivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user