Prevent deadlocks during VirtualDisplay creation
When creating a VirtualDisplay for a VirtualDevice, we need to do some extra work like setting up for input injection, creating a DisplayWindowPolicyController, and grabbing a wakelock to keep the display awake. Some parts of this extra work end up calling back into the DisplayManagerService from another thread, but since we're already holding the mSyncRoot lock we sometimes get into situations where those threads get blocked trying to acquire mSyncRoot, while holding a lock that another thread ends up needing like the global window manager one, so we get deadlock. The fix in this CL is to break up the extra work the VirtualDeviceManagerService needs to do into two parts: one part that happens before the VirtualDisplay is created, and one part after. Neither of these needs mSyncRoot to be held. Fixes: 230544802 Test: atest CreateVirtualDisplayTest Change-Id: I6a6e03f816567579510b3f1ef0705375549a3c88
This commit is contained in:
@@ -19,6 +19,8 @@ package android.companion.virtual;
|
||||
import android.companion.virtual.IVirtualDevice;
|
||||
import android.companion.virtual.IVirtualDeviceActivityListener;
|
||||
import android.companion.virtual.VirtualDeviceParams;
|
||||
import android.hardware.display.IVirtualDisplayCallback;
|
||||
import android.hardware.display.VirtualDisplayConfig;
|
||||
|
||||
/**
|
||||
* Interface for communication between VirtualDeviceManager and VirtualDeviceManagerService.
|
||||
@@ -42,4 +44,16 @@ interface IVirtualDeviceManager {
|
||||
IVirtualDevice createVirtualDevice(
|
||||
in IBinder token, String packageName, int associationId,
|
||||
in VirtualDeviceParams params, in IVirtualDeviceActivityListener activityListener);
|
||||
|
||||
/**
|
||||
* Creates a virtual display owned by a particular virtual device.
|
||||
*
|
||||
* @param virtualDisplayConfig The configuration used in creating the display
|
||||
* @param callback A callback that receives display lifecycle events
|
||||
* @param virtualDevice The device that will own this display
|
||||
* @param packageName The package name of the calling app
|
||||
*/
|
||||
int createVirtualDisplay(in VirtualDisplayConfig virtualDisplayConfig,
|
||||
in IVirtualDisplayCallback callback, in IVirtualDevice virtualDevice,
|
||||
String packageName);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.DisplayManager.VirtualDisplayFlag;
|
||||
import android.hardware.display.DisplayManagerGlobal;
|
||||
import android.hardware.display.IVirtualDisplayCallback;
|
||||
import android.hardware.display.VirtualDisplay;
|
||||
import android.hardware.display.VirtualDisplayConfig;
|
||||
import android.hardware.input.VirtualKeyboard;
|
||||
@@ -65,7 +67,7 @@ import java.util.function.IntConsumer;
|
||||
public final class VirtualDeviceManager {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String LOG_TAG = "VirtualDeviceManager";
|
||||
private static final String TAG = "VirtualDeviceManager";
|
||||
|
||||
private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS =
|
||||
DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
|
||||
@@ -150,6 +152,7 @@ public final class VirtualDeviceManager {
|
||||
public static class VirtualDevice implements AutoCloseable {
|
||||
|
||||
private final Context mContext;
|
||||
private final IVirtualDeviceManager mService;
|
||||
private final IVirtualDevice mVirtualDevice;
|
||||
private final ArrayMap<ActivityListener, ActivityListenerDelegate> mActivityListeners =
|
||||
new ArrayMap<>();
|
||||
@@ -189,6 +192,7 @@ public final class VirtualDeviceManager {
|
||||
Context context,
|
||||
int associationId,
|
||||
VirtualDeviceParams params) throws RemoteException {
|
||||
mService = service;
|
||||
mContext = context.getApplicationContext();
|
||||
mVirtualDevice = service.createVirtualDevice(
|
||||
new Binder(),
|
||||
@@ -274,18 +278,23 @@ public final class VirtualDeviceManager {
|
||||
// TODO(b/205343547): Handle display groups properly instead of creating a new display
|
||||
// group for every new virtual display created using this API.
|
||||
// belongs to the same display group.
|
||||
DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
|
||||
// DisplayManager will call into VirtualDeviceManagerInternal to register the
|
||||
// created displays.
|
||||
return displayManager.createVirtualDisplay(
|
||||
mVirtualDevice,
|
||||
new VirtualDisplayConfig.Builder(
|
||||
getVirtualDisplayName(), width, height, densityDpi)
|
||||
.setSurface(surface)
|
||||
.setFlags(getVirtualDisplayFlags(flags))
|
||||
.build(),
|
||||
callback,
|
||||
executor);
|
||||
VirtualDisplayConfig config = new VirtualDisplayConfig.Builder(
|
||||
getVirtualDisplayName(), width, height, densityDpi)
|
||||
.setSurface(surface)
|
||||
.setFlags(getVirtualDisplayFlags(flags))
|
||||
.build();
|
||||
IVirtualDisplayCallback callbackWrapper =
|
||||
new DisplayManagerGlobal.VirtualDisplayCallback(callback, executor);
|
||||
final int displayId;
|
||||
try {
|
||||
displayId = mService.createVirtualDisplay(config, callbackWrapper, mVirtualDevice,
|
||||
mContext.getPackageName());
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance();
|
||||
return displayManager.createVirtualDisplayWrapper(config, mContext, callbackWrapper,
|
||||
displayId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,7 +31,6 @@ import android.annotation.SystemApi;
|
||||
import android.annotation.SystemService;
|
||||
import android.annotation.TestApi;
|
||||
import android.app.KeyguardManager;
|
||||
import android.companion.virtual.IVirtualDevice;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
@@ -971,17 +970,8 @@ public final class DisplayManager {
|
||||
executor = new HandlerExecutor(
|
||||
Handler.createAsync(handler != null ? handler.getLooper() : Looper.myLooper()));
|
||||
}
|
||||
return mGlobal.createVirtualDisplay(mContext, projection, null /* virtualDevice */,
|
||||
virtualDisplayConfig, callback, executor, windowContext);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public VirtualDisplay createVirtualDisplay(@Nullable IVirtualDevice virtualDevice,
|
||||
@NonNull VirtualDisplayConfig virtualDisplayConfig,
|
||||
@Nullable VirtualDisplay.Callback callback,
|
||||
@Nullable Executor executor) {
|
||||
return mGlobal.createVirtualDisplay(mContext, null /* projection */, virtualDevice,
|
||||
virtualDisplayConfig, callback, executor, null);
|
||||
return mGlobal.createVirtualDisplay(mContext, projection, virtualDisplayConfig, callback,
|
||||
executor, windowContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.PropertyInvalidatedCache;
|
||||
import android.companion.virtual.IVirtualDevice;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
@@ -586,18 +585,28 @@ public final class DisplayManagerGlobal {
|
||||
}
|
||||
|
||||
public VirtualDisplay createVirtualDisplay(@NonNull Context context, MediaProjection projection,
|
||||
IVirtualDevice virtualDevice, @NonNull VirtualDisplayConfig virtualDisplayConfig,
|
||||
VirtualDisplay.Callback callback, @Nullable Executor executor,
|
||||
@Nullable Context windowContext) {
|
||||
@NonNull VirtualDisplayConfig virtualDisplayConfig, VirtualDisplay.Callback callback,
|
||||
@Nullable Executor executor, @Nullable Context windowContext) {
|
||||
VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, executor);
|
||||
IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
|
||||
int displayId;
|
||||
try {
|
||||
displayId = mDm.createVirtualDisplay(virtualDisplayConfig, callbackWrapper,
|
||||
projectionToken, virtualDevice, context.getPackageName());
|
||||
projectionToken, context.getPackageName());
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
return createVirtualDisplayWrapper(virtualDisplayConfig, windowContext, callbackWrapper,
|
||||
displayId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a VirtualDisplay wrapper object for a newly created virtual display ; to be called
|
||||
* once the display has been created in system_server.
|
||||
*/
|
||||
@Nullable
|
||||
public VirtualDisplay createVirtualDisplayWrapper(VirtualDisplayConfig virtualDisplayConfig,
|
||||
Context windowContext, IVirtualDisplayCallback callbackWrapper, int displayId) {
|
||||
if (displayId < 0) {
|
||||
Log.e(TAG, "Could not create virtual display: " + virtualDisplayConfig.getName());
|
||||
return null;
|
||||
@@ -1050,7 +1059,10 @@ public final class DisplayManagerGlobal {
|
||||
}
|
||||
}
|
||||
|
||||
private final static class VirtualDisplayCallback extends IVirtualDisplayCallback.Stub {
|
||||
/**
|
||||
* Assists in dispatching VirtualDisplay lifecycle event callbacks on a given Executor.
|
||||
*/
|
||||
public static final class VirtualDisplayCallback extends IVirtualDisplayCallback.Stub {
|
||||
@Nullable private final VirtualDisplay.Callback mCallback;
|
||||
@Nullable private final Executor mExecutor;
|
||||
|
||||
@@ -1062,7 +1074,7 @@ public final class DisplayManagerGlobal {
|
||||
* @param executor The executor to call the {@code callback} on. Must not be {@code null} if
|
||||
* the callback is not {@code null}.
|
||||
*/
|
||||
VirtualDisplayCallback(VirtualDisplay.Callback callback, Executor executor) {
|
||||
public VirtualDisplayCallback(VirtualDisplay.Callback callback, Executor executor) {
|
||||
mCallback = callback;
|
||||
mExecutor = mCallback != null ? Objects.requireNonNull(executor) : null;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.hardware.display;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.companion.virtual.IVirtualDevice;
|
||||
import android.graphics.Point;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Handler;
|
||||
@@ -59,6 +60,14 @@ public abstract class DisplayManagerInternal {
|
||||
public abstract void initPowerManagement(DisplayPowerCallbacks callbacks,
|
||||
Handler handler, SensorManager sensorManager);
|
||||
|
||||
/**
|
||||
* Called by the VirtualDeviceManagerService to create a VirtualDisplay owned by a
|
||||
* VirtualDevice.
|
||||
*/
|
||||
public abstract int createVirtualDisplay(VirtualDisplayConfig config,
|
||||
IVirtualDisplayCallback callback, IVirtualDevice virtualDevice,
|
||||
DisplayWindowPolicyController dwpc, String packageName);
|
||||
|
||||
/**
|
||||
* Called by the power manager to request a new power state.
|
||||
* <p>
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package android.hardware.display;
|
||||
|
||||
import android.companion.virtual.IVirtualDevice;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.graphics.Point;
|
||||
import android.hardware.display.BrightnessConfiguration;
|
||||
@@ -88,10 +87,10 @@ interface IDisplayManager {
|
||||
void requestColorMode(int displayId, int colorMode);
|
||||
|
||||
// Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate
|
||||
// MediaProjection token or VirtualDevice for certain combinations of flags.
|
||||
// MediaProjection token for certain combinations of flags.
|
||||
int createVirtualDisplay(in VirtualDisplayConfig virtualDisplayConfig,
|
||||
in IVirtualDisplayCallback callback, in IMediaProjection projectionToken,
|
||||
in IVirtualDevice virtualDevice, String packageName);
|
||||
String packageName);
|
||||
|
||||
// No permissions required, but must be same Uid as the creator.
|
||||
void resizeVirtualDisplay(in IVirtualDisplayCallback token,
|
||||
|
||||
@@ -48,7 +48,6 @@ import com.android.internal.app.BlockedAppStreamingActivity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
/**
|
||||
@@ -66,6 +65,14 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
void onRunningAppsChanged(ArraySet<Integer> runningUids);
|
||||
}
|
||||
|
||||
/**
|
||||
* For communicating when activities are blocked from running on the display by this policy
|
||||
* controller.
|
||||
*/
|
||||
public interface ActivityBlockedCallback {
|
||||
/** Called when an activity is blocked.*/
|
||||
void onActivityBlocked(int displayId, ActivityInfo activityInfo);
|
||||
}
|
||||
private static final ComponentName BLOCKED_APP_STREAMING_COMPONENT =
|
||||
new ComponentName("android", BlockedAppStreamingActivity.class.getName());
|
||||
|
||||
@@ -89,7 +96,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
private final Object mGenericWindowPolicyControllerLock = new Object();
|
||||
@ActivityPolicy
|
||||
private final int mDefaultActivityPolicy;
|
||||
private final Consumer<ActivityInfo> mActivityBlockedCallback;
|
||||
private final ActivityBlockedCallback mActivityBlockedCallback;
|
||||
private int mDisplayId = Display.INVALID_DISPLAY;
|
||||
|
||||
@NonNull
|
||||
@GuardedBy("mGenericWindowPolicyControllerLock")
|
||||
@@ -98,6 +106,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private final ArraySet<RunningAppsChangedListener> mRunningAppsChangedListener =
|
||||
new ArraySet<>();
|
||||
@Nullable
|
||||
private final @AssociationRequest.DeviceProfile String mDeviceProfile;
|
||||
|
||||
/**
|
||||
@@ -119,8 +128,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
* {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_ALLOWED}
|
||||
* @param defaultActivityPolicy Whether activities are default allowed to be displayed or
|
||||
* blocked.
|
||||
* @param activityListener Activity listener to listen for activity changes. The display ID
|
||||
* is not populated in this callback and is always {@link Display#INVALID_DISPLAY}.
|
||||
* @param activityListener Activity listener to listen for activity changes.
|
||||
* @param activityBlockedCallback Callback that is called when an activity is blocked from
|
||||
* launching.
|
||||
* @param deviceProfile The {@link AssociationRequest.DeviceProfile} of this virtual device.
|
||||
@@ -133,7 +141,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
@NonNull Set<ComponentName> blockedActivities,
|
||||
@ActivityPolicy int defaultActivityPolicy,
|
||||
@NonNull ActivityListener activityListener,
|
||||
@NonNull Consumer<ActivityInfo> activityBlockedCallback,
|
||||
@NonNull ActivityBlockedCallback activityBlockedCallback,
|
||||
@AssociationRequest.DeviceProfile String deviceProfile) {
|
||||
super();
|
||||
mAllowedUsers = allowedUsers;
|
||||
@@ -148,6 +156,13 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
mDeviceProfile = deviceProfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected to be called once this object is associated with a newly created display.
|
||||
*/
|
||||
public void setDisplayId(int displayId) {
|
||||
mDisplayId = displayId;
|
||||
}
|
||||
|
||||
/** Register a listener for running applications changes. */
|
||||
public void registerRunningAppsChangedListener(@NonNull RunningAppsChangedListener listener) {
|
||||
mRunningAppsChangedListener.add(listener);
|
||||
@@ -169,7 +184,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
for (int i = 0; i < activityCount; i++) {
|
||||
final ActivityInfo aInfo = activities.get(i);
|
||||
if (!canContainActivity(aInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) {
|
||||
mActivityBlockedCallback.accept(aInfo);
|
||||
mActivityBlockedCallback.onActivityBlocked(mDisplayId, aInfo);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -191,7 +206,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
}
|
||||
|
||||
if (!canContainActivity(activityInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) {
|
||||
mActivityBlockedCallback.accept(activityInfo);
|
||||
mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -201,14 +216,14 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
if (isNewTask && !mBlockedCrossTaskNavigations.isEmpty()
|
||||
&& mBlockedCrossTaskNavigations.contains(activityComponent)) {
|
||||
Slog.d(TAG, "Virtual device blocking cross task navigation of " + activityComponent);
|
||||
mActivityBlockedCallback.accept(activityInfo);
|
||||
mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
|
||||
return false;
|
||||
}
|
||||
if (isNewTask && !mAllowedCrossTaskNavigations.isEmpty()
|
||||
&& !mAllowedCrossTaskNavigations.contains(activityComponent)) {
|
||||
Slog.d(TAG, "Virtual device not allowing cross task navigation of "
|
||||
+ activityComponent);
|
||||
mActivityBlockedCallback.accept(activityInfo);
|
||||
mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -220,7 +235,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
public boolean keepActivityOnWindowFlagsChanged(ActivityInfo activityInfo, int windowFlags,
|
||||
int systemWindowFlags) {
|
||||
if (!canContainActivity(activityInfo, windowFlags, systemWindowFlags)) {
|
||||
mActivityBlockedCallback.accept(activityInfo);
|
||||
mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -234,7 +249,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
if (mActivityListener != null && topActivity != null) {
|
||||
// Post callback on the main thread so it doesn't block activity launching
|
||||
mHandler.post(() ->
|
||||
mActivityListener.onTopActivityChanged(Display.INVALID_DISPLAY, topActivity));
|
||||
mActivityListener.onTopActivityChanged(mDisplayId, topActivity));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +260,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
mRunningUids.addAll(runningUids);
|
||||
if (mActivityListener != null && mRunningUids.isEmpty()) {
|
||||
// Post callback on the main thread so it doesn't block activity launching
|
||||
mHandler.post(() -> mActivityListener.onDisplayEmpty(Display.INVALID_DISPLAY));
|
||||
mHandler.post(() -> mActivityListener.onDisplayEmpty(mDisplayId));
|
||||
}
|
||||
}
|
||||
mHandler.post(() -> {
|
||||
@@ -257,7 +272,10 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
|
||||
@Override
|
||||
public boolean canShowTasksInRecents() {
|
||||
// TODO(b/234075973) : Remove this once proper API is ready.
|
||||
if (mDeviceProfile == null) {
|
||||
return true;
|
||||
}
|
||||
// TODO(b/234075973) : Remove this once proper API is ready.
|
||||
switch (mDeviceProfile) {
|
||||
case DEVICE_PROFILE_AUTOMOTIVE_PROJECTION:
|
||||
return false;
|
||||
|
||||
@@ -64,7 +64,6 @@ import android.util.SparseArray;
|
||||
import android.view.Display;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
import android.window.DisplayWindowPolicyController;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -110,11 +109,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
|
||||
@GuardedBy("mVirtualDeviceLock")
|
||||
private boolean mDefaultShowPointerIcon = true;
|
||||
|
||||
private ActivityListener createListenerAdapter(int displayId) {
|
||||
private ActivityListener createListenerAdapter() {
|
||||
return new ActivityListener() {
|
||||
|
||||
@Override
|
||||
public void onTopActivityChanged(int unusedDisplayId, ComponentName topActivity) {
|
||||
public void onTopActivityChanged(int displayId, ComponentName topActivity) {
|
||||
try {
|
||||
mActivityListener.onTopActivityChanged(displayId, topActivity);
|
||||
} catch (RemoteException e) {
|
||||
@@ -123,7 +122,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayEmpty(int unusedDisplayId) {
|
||||
public void onDisplayEmpty(int displayId) {
|
||||
try {
|
||||
mActivityListener.onDisplayEmpty(displayId);
|
||||
} catch (RemoteException e) {
|
||||
@@ -529,24 +528,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
|
||||
mInputController.dump(fout);
|
||||
}
|
||||
|
||||
DisplayWindowPolicyController onVirtualDisplayCreatedLocked(int displayId) {
|
||||
GenericWindowPolicyController createWindowPolicyController() {
|
||||
synchronized (mVirtualDeviceLock) {
|
||||
if (mVirtualDisplayIds.contains(displayId)) {
|
||||
throw new IllegalStateException(
|
||||
"Virtual device already have a virtual display with ID " + displayId);
|
||||
}
|
||||
mVirtualDisplayIds.add(displayId);
|
||||
mInputController.setShowPointerIcon(mDefaultShowPointerIcon, displayId);
|
||||
mInputController.setPointerAcceleration(1f, displayId);
|
||||
mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false,
|
||||
displayId);
|
||||
mInputController.setLocalIme(displayId);
|
||||
|
||||
// Since we're being called in the middle of the display being created, we post a
|
||||
// task to grab the wakelock instead of doing it synchronously here, to avoid
|
||||
// reentrancy problems.
|
||||
mContext.getMainThreadHandler().post(() -> addWakeLockForDisplay(displayId));
|
||||
|
||||
final GenericWindowPolicyController gwpc =
|
||||
new GenericWindowPolicyController(FLAG_SECURE,
|
||||
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
|
||||
@@ -556,19 +539,36 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
|
||||
mParams.getAllowedActivities(),
|
||||
mParams.getBlockedActivities(),
|
||||
mParams.getDefaultActivityPolicy(),
|
||||
createListenerAdapter(displayId),
|
||||
activityInfo -> onActivityBlocked(displayId, activityInfo),
|
||||
createListenerAdapter(),
|
||||
this::onActivityBlocked,
|
||||
mAssociationInfo.getDeviceProfile());
|
||||
gwpc.registerRunningAppsChangedListener(/* listener= */ this);
|
||||
mWindowPolicyControllers.put(displayId, gwpc);
|
||||
return gwpc;
|
||||
}
|
||||
}
|
||||
|
||||
void addWakeLockForDisplay(int displayId) {
|
||||
void onVirtualDisplayCreatedLocked(GenericWindowPolicyController gwpc, int displayId) {
|
||||
synchronized (mVirtualDeviceLock) {
|
||||
if (!mVirtualDisplayIds.contains(displayId)
|
||||
|| mPerDisplayWakelocks.containsKey(displayId)) {
|
||||
if (displayId == Display.INVALID_DISPLAY) {
|
||||
return;
|
||||
}
|
||||
if (mVirtualDisplayIds.contains(displayId)) {
|
||||
throw new IllegalStateException(
|
||||
"Virtual device already has a virtual display with ID " + displayId);
|
||||
}
|
||||
mVirtualDisplayIds.add(displayId);
|
||||
|
||||
gwpc.setDisplayId(displayId);
|
||||
mWindowPolicyControllers.put(displayId, gwpc);
|
||||
|
||||
mInputController.setShowPointerIcon(mDefaultShowPointerIcon, displayId);
|
||||
mInputController.setPointerAcceleration(1f, displayId);
|
||||
mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false,
|
||||
displayId);
|
||||
mInputController.setLocalIme(displayId);
|
||||
|
||||
|
||||
if (mPerDisplayWakelocks.containsKey(displayId)) {
|
||||
Slog.e(TAG, "Not creating wakelock for displayId " + displayId);
|
||||
return;
|
||||
}
|
||||
@@ -576,8 +576,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
|
||||
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
|
||||
PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
|
||||
TAG + ":" + displayId, displayId);
|
||||
wakeLock.acquire();
|
||||
mPerDisplayWakelocks.put(displayId, wakeLock);
|
||||
wakeLock.acquire();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,10 @@ import android.companion.virtual.IVirtualDeviceManager;
|
||||
import android.companion.virtual.VirtualDeviceManager;
|
||||
import android.companion.virtual.VirtualDeviceParams;
|
||||
import android.content.Context;
|
||||
import android.hardware.display.DisplayManagerInternal;
|
||||
import android.hardware.display.IVirtualDisplayCallback;
|
||||
import android.hardware.display.VirtualDisplayConfig;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
@@ -41,9 +45,9 @@ import android.util.ExceptionUtils;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.widget.Toast;
|
||||
import android.window.DisplayWindowPolicyController;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.companion.virtual.VirtualDeviceImpl.PendingTrampoline;
|
||||
@@ -203,6 +207,7 @@ public class VirtualDeviceManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
class VirtualDeviceManagerImpl extends IVirtualDeviceManager.Stub implements
|
||||
VirtualDeviceImpl.PendingTrampolineCallback {
|
||||
|
||||
@@ -265,6 +270,50 @@ public class VirtualDeviceManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
|
||||
IVirtualDisplayCallback callback, IVirtualDevice virtualDevice, String packageName)
|
||||
throws RemoteException {
|
||||
final int callingUid = getCallingUid();
|
||||
if (!PermissionUtils.validateCallingPackageName(getContext(), packageName)) {
|
||||
throw new SecurityException(
|
||||
"Package name " + packageName + " does not belong to calling uid "
|
||||
+ callingUid);
|
||||
}
|
||||
VirtualDeviceImpl virtualDeviceImpl;
|
||||
synchronized (mVirtualDeviceManagerLock) {
|
||||
virtualDeviceImpl = mVirtualDevices.get(virtualDevice.getAssociationId());
|
||||
if (virtualDeviceImpl == null) {
|
||||
throw new SecurityException("Invalid VirtualDevice");
|
||||
}
|
||||
}
|
||||
if (virtualDeviceImpl.getOwnerUid() != callingUid) {
|
||||
throw new SecurityException(
|
||||
"uid " + callingUid
|
||||
+ " is not the owner of the supplied VirtualDevice");
|
||||
}
|
||||
GenericWindowPolicyController gwpc;
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
gwpc = virtualDeviceImpl.createWindowPolicyController();
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
|
||||
DisplayManagerInternal displayManager = getLocalService(
|
||||
DisplayManagerInternal.class);
|
||||
int displayId = displayManager.createVirtualDisplay(virtualDisplayConfig, callback,
|
||||
virtualDevice, gwpc, packageName);
|
||||
|
||||
final long tokenTwo = Binder.clearCallingIdentity();
|
||||
try {
|
||||
virtualDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, displayId);
|
||||
return displayId;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(tokenTwo);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private AssociationInfo getAssociationInfo(String packageName, int associationId) {
|
||||
final int callingUserId = getCallingUserHandle().getIdentifier();
|
||||
@@ -336,14 +385,6 @@ public class VirtualDeviceManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisplayWindowPolicyController onVirtualDisplayCreated(IVirtualDevice virtualDevice,
|
||||
int displayId) {
|
||||
synchronized (mVirtualDeviceManagerLock) {
|
||||
return ((VirtualDeviceImpl) virtualDevice).onVirtualDisplayCreatedLocked(displayId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVirtualDisplayRemoved(IVirtualDevice virtualDevice, int displayId) {
|
||||
synchronized (mVirtualDeviceManagerLock) {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.server.companion.virtual;
|
||||
|
||||
import android.companion.virtual.IVirtualDevice;
|
||||
import android.window.DisplayWindowPolicyController;
|
||||
|
||||
/**
|
||||
* Virtual device manager local service interface.
|
||||
@@ -30,17 +29,6 @@ public abstract class VirtualDeviceManagerInternal {
|
||||
*/
|
||||
public abstract boolean isValidVirtualDevice(IVirtualDevice virtualDevice);
|
||||
|
||||
/**
|
||||
* Notify a virtual display is created.
|
||||
*
|
||||
* @param virtualDevice The virtual device where the virtual display located.
|
||||
* @param displayId The display id of the created virtual display.
|
||||
*
|
||||
* @return The {@link DisplayWindowPolicyController} of the virtual device.
|
||||
*/
|
||||
public abstract DisplayWindowPolicyController onVirtualDisplayCreated(
|
||||
IVirtualDevice virtualDevice, int displayId);
|
||||
|
||||
/**
|
||||
* Notify a virtual display is removed.
|
||||
*
|
||||
|
||||
@@ -1231,7 +1231,7 @@ public final class DisplayManagerService extends SystemService {
|
||||
|
||||
private int createVirtualDisplayInternal(VirtualDisplayConfig virtualDisplayConfig,
|
||||
IVirtualDisplayCallback callback, IMediaProjection projection,
|
||||
IVirtualDevice virtualDevice, String packageName) {
|
||||
IVirtualDevice virtualDevice, DisplayWindowPolicyController dwpc, String packageName) {
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
if (!validatePackageName(callingUid, packageName)) {
|
||||
throw new SecurityException("packageName must match the calling uid");
|
||||
@@ -1351,8 +1351,13 @@ public final class DisplayManagerService extends SystemService {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mSyncRoot) {
|
||||
return createVirtualDisplayLocked(callback, projection, virtualDevice, callingUid,
|
||||
final int displayId = createVirtualDisplayLocked(callback, projection, callingUid,
|
||||
packageName, surface, flags, virtualDisplayConfig);
|
||||
if (displayId != Display.INVALID_DISPLAY && virtualDevice != null && dwpc != null) {
|
||||
mDisplayWindowPolicyControllers.put(displayId,
|
||||
Pair.create(virtualDevice, dwpc));
|
||||
}
|
||||
return displayId;
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
@@ -1360,8 +1365,7 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
|
||||
private int createVirtualDisplayLocked(IVirtualDisplayCallback callback,
|
||||
IMediaProjection projection, IVirtualDevice virtualDevice,
|
||||
int callingUid, String packageName, Surface surface,
|
||||
IMediaProjection projection, int callingUid, String packageName, Surface surface,
|
||||
int flags, VirtualDisplayConfig virtualDisplayConfig) {
|
||||
if (mVirtualDisplayAdapter == null) {
|
||||
Slog.w(TAG, "Rejecting request to create private virtual display "
|
||||
@@ -1389,16 +1393,7 @@ public final class DisplayManagerService extends SystemService {
|
||||
|
||||
final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
|
||||
if (display != null) {
|
||||
final int displayId = display.getDisplayIdLocked();
|
||||
if (virtualDevice != null) {
|
||||
final VirtualDeviceManagerInternal vdm =
|
||||
getLocalService(VirtualDeviceManagerInternal.class);
|
||||
final DisplayWindowPolicyController controller =
|
||||
vdm.onVirtualDisplayCreated(virtualDevice, displayId);
|
||||
mDisplayWindowPolicyControllers.put(displayId,
|
||||
Pair.create(virtualDevice, controller));
|
||||
}
|
||||
return displayId;
|
||||
return display.getDisplayIdLocked();
|
||||
}
|
||||
|
||||
// Something weird happened and the logical display was not created.
|
||||
@@ -3066,9 +3061,9 @@ public final class DisplayManagerService extends SystemService {
|
||||
@Override // Binder call
|
||||
public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
|
||||
IVirtualDisplayCallback callback, IMediaProjection projection,
|
||||
IVirtualDevice virtualDeviceToken, String packageName) {
|
||||
String packageName) {
|
||||
return createVirtualDisplayInternal(virtualDisplayConfig, callback, projection,
|
||||
virtualDeviceToken, packageName);
|
||||
null, null, packageName);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
@@ -3534,7 +3529,8 @@ public final class DisplayManagerService extends SystemService {
|
||||
return !Float.isNaN(refreshRate) && (refreshRate > 0.0f);
|
||||
}
|
||||
|
||||
private final class LocalService extends DisplayManagerInternal {
|
||||
@VisibleForTesting
|
||||
final class LocalService extends DisplayManagerInternal {
|
||||
|
||||
@Override
|
||||
public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
|
||||
@@ -3549,6 +3545,14 @@ public final class DisplayManagerService extends SystemService {
|
||||
mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATIONS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int createVirtualDisplay(VirtualDisplayConfig config,
|
||||
IVirtualDisplayCallback callback, IVirtualDevice virtualDevice,
|
||||
DisplayWindowPolicyController dwpc, String packageName) {
|
||||
return createVirtualDisplayInternal(config, callback, null, virtualDevice, dwpc,
|
||||
packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requestPowerState(int groupId, DisplayPowerRequest request,
|
||||
boolean waitForNegativeProximity) {
|
||||
|
||||
@@ -228,36 +228,36 @@ public class VirtualDeviceManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void onVirtualDisplayRemovedLocked_doesNotThrowException() {
|
||||
final int displayId = 2;
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(displayId);
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
// This call should not throw any exceptions.
|
||||
mDeviceImpl.onVirtualDisplayRemovedLocked(displayId);
|
||||
mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onVirtualDisplayCreatedLocked_wakeLockIsAcquired() throws RemoteException {
|
||||
final int displayId = 2;
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(displayId);
|
||||
verify(mIPowerManagerMock, never()).acquireWakeLock(any(Binder.class), anyInt(),
|
||||
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
|
||||
nullable(String.class), anyInt(), eq(null));
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(),
|
||||
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
|
||||
nullable(String.class), eq(displayId), eq(null));
|
||||
nullable(String.class), eq(DISPLAY_ID), eq(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onVirtualDisplayCreatedLocked_duplicateCalls_onlyOneWakeLockIsAcquired()
|
||||
throws RemoteException {
|
||||
final int displayId = 2;
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(displayId);
|
||||
GenericWindowPolicyController gwpc = mDeviceImpl.createWindowPolicyController();
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
assertThrows(IllegalStateException.class,
|
||||
() -> mDeviceImpl.onVirtualDisplayCreatedLocked(displayId));
|
||||
() -> mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID));
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(),
|
||||
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
|
||||
nullable(String.class), eq(displayId), eq(null));
|
||||
nullable(String.class), eq(DISPLAY_ID), eq(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -269,30 +269,30 @@ public class VirtualDeviceManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void onVirtualDisplayRemovedLocked_wakeLockIsReleased() throws RemoteException {
|
||||
final int displayId = 2;
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(displayId);
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class);
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(),
|
||||
anyInt(),
|
||||
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
|
||||
nullable(String.class), eq(displayId), eq(null));
|
||||
nullable(String.class), eq(DISPLAY_ID), eq(null));
|
||||
|
||||
IBinder wakeLock = wakeLockCaptor.getValue();
|
||||
mDeviceImpl.onVirtualDisplayRemovedLocked(displayId);
|
||||
mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID);
|
||||
verify(mIPowerManagerMock, Mockito.times(1)).releaseWakeLock(eq(wakeLock), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addVirtualDisplay_displayNotReleased_wakeLockIsReleased() throws RemoteException {
|
||||
final int displayId = 2;
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(displayId);
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class);
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(),
|
||||
anyInt(),
|
||||
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
|
||||
nullable(String.class), eq(displayId), eq(null));
|
||||
nullable(String.class), eq(DISPLAY_ID), eq(null));
|
||||
IBinder wakeLock = wakeLockCaptor.getValue();
|
||||
|
||||
// Close the VirtualDevice without first notifying it of the VirtualDisplay removal.
|
||||
@@ -416,7 +416,8 @@ public class VirtualDeviceManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void onAudioSessionStarting_hasVirtualAudioController() {
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID);
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
|
||||
mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback);
|
||||
|
||||
@@ -425,7 +426,8 @@ public class VirtualDeviceManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void onAudioSessionEnded_noVirtualAudioController() {
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID);
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback);
|
||||
|
||||
mDeviceImpl.onAudioSessionEnded();
|
||||
@@ -435,7 +437,8 @@ public class VirtualDeviceManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void close_cleanVirtualAudioController() {
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID);
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback);
|
||||
|
||||
mDeviceImpl.close();
|
||||
@@ -659,7 +662,8 @@ public class VirtualDeviceManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void openNonBlockedAppOnVirtualDisplay_doesNotStartBlockedAlertActivity() {
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID);
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
|
||||
DISPLAY_ID);
|
||||
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
|
||||
@@ -677,7 +681,8 @@ public class VirtualDeviceManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void openPermissionControllerOnVirtualDisplay_startBlockedAlertActivity() {
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID);
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
|
||||
DISPLAY_ID);
|
||||
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
|
||||
@@ -695,7 +700,8 @@ public class VirtualDeviceManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void openSettingsOnVirtualDisplay_startBlockedAlertActivity() {
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID);
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
|
||||
DISPLAY_ID);
|
||||
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
|
||||
@@ -713,7 +719,8 @@ public class VirtualDeviceManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void openVendingOnVirtualDisplay_startBlockedAlertActivity() {
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID);
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
|
||||
DISPLAY_ID);
|
||||
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
|
||||
@@ -731,7 +738,8 @@ public class VirtualDeviceManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void openGoogleDialerOnVirtualDisplay_startBlockedAlertActivity() {
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID);
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
|
||||
DISPLAY_ID);
|
||||
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
|
||||
@@ -749,7 +757,8 @@ public class VirtualDeviceManagerServiceTest {
|
||||
|
||||
@Test
|
||||
public void openGoogleMapsOnVirtualDisplay_startBlockedAlertActivity() {
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID);
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
|
||||
DISPLAY_ID);
|
||||
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
|
||||
|
||||
@@ -45,6 +45,7 @@ import android.hardware.display.BrightnessConfiguration;
|
||||
import android.hardware.display.Curve;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.DisplayManagerGlobal;
|
||||
import android.hardware.display.DisplayManagerInternal;
|
||||
import android.hardware.display.DisplayViewport;
|
||||
import android.hardware.display.DisplayedContentSample;
|
||||
import android.hardware.display.DisplayedContentSamplingAttributes;
|
||||
@@ -63,6 +64,7 @@ import android.view.DisplayEventReceiver;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.DisplayWindowPolicyController;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
@@ -220,7 +222,7 @@ public class DisplayManagerServiceTest {
|
||||
builder.setUniqueId(uniqueId);
|
||||
builder.setFlags(flags);
|
||||
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
|
||||
null /* projection */, null /* virtualDeviceToken */, PACKAGE_NAME);
|
||||
null /* projection */, PACKAGE_NAME);
|
||||
|
||||
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
|
||||
|
||||
@@ -346,7 +348,7 @@ public class DisplayManagerServiceTest {
|
||||
builder.setFlags(flags);
|
||||
builder.setUniqueId(uniqueId);
|
||||
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
|
||||
null /* projection */, null /* virtualDeviceToken */, PACKAGE_NAME);
|
||||
null /* projection */, PACKAGE_NAME);
|
||||
|
||||
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
|
||||
|
||||
@@ -586,8 +588,7 @@ public class DisplayManagerServiceTest {
|
||||
VIRTUAL_DISPLAY_NAME, width, height, dpi);
|
||||
builder.setUniqueId(uniqueId);
|
||||
final int firstDisplayId = binderService.createVirtualDisplay(builder.build(),
|
||||
mMockAppToken /* callback */, null /* projection */, null /* virtualDeviceToken */,
|
||||
PACKAGE_NAME);
|
||||
mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
|
||||
|
||||
// The second virtual display requests to mirror the first virtual display.
|
||||
final String uniqueId2 = "uniqueId --- displayIdToMirrorTest #2";
|
||||
@@ -598,7 +599,7 @@ public class DisplayManagerServiceTest {
|
||||
builder2.setDisplayIdToMirror(firstDisplayId);
|
||||
final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(),
|
||||
mMockAppToken2 /* callback */, null /* projection */,
|
||||
null /* virtualDeviceToken */, PACKAGE_NAME);
|
||||
PACKAGE_NAME);
|
||||
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
|
||||
|
||||
// flush the handler
|
||||
@@ -636,8 +637,7 @@ public class DisplayManagerServiceTest {
|
||||
builder.setSurface(surface);
|
||||
builder.setUniqueId(uniqueId);
|
||||
final int displayId = binderService.createVirtualDisplay(builder.build(),
|
||||
mMockAppToken /* callback */, null /* projection */, null /* virtualDeviceToken */,
|
||||
PACKAGE_NAME);
|
||||
mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
|
||||
|
||||
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
|
||||
|
||||
@@ -669,7 +669,7 @@ public class DisplayManagerServiceTest {
|
||||
builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP");
|
||||
|
||||
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
|
||||
null /* projection */, null /* virtualDeviceToken */, PACKAGE_NAME);
|
||||
null /* projection */, PACKAGE_NAME);
|
||||
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
|
||||
displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
|
||||
DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
|
||||
@@ -700,7 +700,7 @@ public class DisplayManagerServiceTest {
|
||||
|
||||
try {
|
||||
bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
|
||||
null /* projection */, null /* virtualDeviceToken */, PACKAGE_NAME);
|
||||
null /* projection */, PACKAGE_NAME);
|
||||
fail("Creating virtual display with VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP without "
|
||||
+ "ADD_TRUSTED_DISPLAY permission should throw SecurityException.");
|
||||
} catch (SecurityException e) {
|
||||
@@ -716,6 +716,8 @@ public class DisplayManagerServiceTest {
|
||||
public void testOwnDisplayGroup_allowCreationWithVirtualDevice() {
|
||||
DisplayManagerService displayManager =
|
||||
new DisplayManagerService(mContext, mBasicInjector);
|
||||
DisplayManagerInternal localService = displayManager.new LocalService();
|
||||
|
||||
registerDefaultDisplays(displayManager);
|
||||
|
||||
DisplayManagerService.BinderService bs = displayManager.new BinderService();
|
||||
@@ -733,8 +735,9 @@ public class DisplayManagerServiceTest {
|
||||
when(mMockVirtualDeviceManagerInternal.isValidVirtualDevice(virtualDevice))
|
||||
.thenReturn(true);
|
||||
|
||||
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
|
||||
null /* projection */, virtualDevice /* virtualDeviceToken */, PACKAGE_NAME);
|
||||
int displayId = localService.createVirtualDisplay(builder.build(),
|
||||
mMockAppToken /* callback */, virtualDevice /* virtualDeviceToken */,
|
||||
mock(DisplayWindowPolicyController.class), PACKAGE_NAME);
|
||||
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
|
||||
displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
|
||||
DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
|
||||
|
||||
Reference in New Issue
Block a user