Merge "Prevent deadlocks during VirtualDisplay creation" into tm-dev

This commit is contained in:
Antony Sargent
2022-05-30 00:09:18 +00:00
committed by Android (Google) Code Review
13 changed files with 248 additions and 152 deletions

View File

@@ -19,6 +19,8 @@ package android.companion.virtual;
import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceActivityListener; import android.companion.virtual.IVirtualDeviceActivityListener;
import android.companion.virtual.VirtualDeviceParams; import android.companion.virtual.VirtualDeviceParams;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplayConfig;
/** /**
* Interface for communication between VirtualDeviceManager and VirtualDeviceManagerService. * Interface for communication between VirtualDeviceManager and VirtualDeviceManagerService.
@@ -42,4 +44,16 @@ interface IVirtualDeviceManager {
IVirtualDevice createVirtualDevice( IVirtualDevice createVirtualDevice(
in IBinder token, String packageName, int associationId, in IBinder token, String packageName, int associationId,
in VirtualDeviceParams params, in IVirtualDeviceActivityListener activityListener); 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);
} }

View File

@@ -33,6 +33,8 @@ import android.content.Context;
import android.graphics.Point; import android.graphics.Point;
import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.VirtualDisplayFlag; 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.VirtualDisplay;
import android.hardware.display.VirtualDisplayConfig; import android.hardware.display.VirtualDisplayConfig;
import android.hardware.input.VirtualKeyboard; import android.hardware.input.VirtualKeyboard;
@@ -65,7 +67,7 @@ import java.util.function.IntConsumer;
public final class VirtualDeviceManager { public final class VirtualDeviceManager {
private static final boolean DEBUG = false; 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 = private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS =
DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
@@ -150,6 +152,7 @@ public final class VirtualDeviceManager {
public static class VirtualDevice implements AutoCloseable { public static class VirtualDevice implements AutoCloseable {
private final Context mContext; private final Context mContext;
private final IVirtualDeviceManager mService;
private final IVirtualDevice mVirtualDevice; private final IVirtualDevice mVirtualDevice;
private final ArrayMap<ActivityListener, ActivityListenerDelegate> mActivityListeners = private final ArrayMap<ActivityListener, ActivityListenerDelegate> mActivityListeners =
new ArrayMap<>(); new ArrayMap<>();
@@ -189,6 +192,7 @@ public final class VirtualDeviceManager {
Context context, Context context,
int associationId, int associationId,
VirtualDeviceParams params) throws RemoteException { VirtualDeviceParams params) throws RemoteException {
mService = service;
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();
mVirtualDevice = service.createVirtualDevice( mVirtualDevice = service.createVirtualDevice(
new Binder(), new Binder(),
@@ -274,18 +278,23 @@ public final class VirtualDeviceManager {
// TODO(b/205343547): Handle display groups properly instead of creating a new display // TODO(b/205343547): Handle display groups properly instead of creating a new display
// group for every new virtual display created using this API. // group for every new virtual display created using this API.
// belongs to the same display group. // belongs to the same display group.
DisplayManager displayManager = mContext.getSystemService(DisplayManager.class); VirtualDisplayConfig config = new VirtualDisplayConfig.Builder(
// DisplayManager will call into VirtualDeviceManagerInternal to register the getVirtualDisplayName(), width, height, densityDpi)
// created displays. .setSurface(surface)
return displayManager.createVirtualDisplay( .setFlags(getVirtualDisplayFlags(flags))
mVirtualDevice, .build();
new VirtualDisplayConfig.Builder( IVirtualDisplayCallback callbackWrapper =
getVirtualDisplayName(), width, height, densityDpi) new DisplayManagerGlobal.VirtualDisplayCallback(callback, executor);
.setSurface(surface) final int displayId;
.setFlags(getVirtualDisplayFlags(flags)) try {
.build(), displayId = mService.createVirtualDisplay(config, callbackWrapper, mVirtualDevice,
callback, mContext.getPackageName());
executor); } catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance();
return displayManager.createVirtualDisplayWrapper(config, mContext, callbackWrapper,
displayId);
} }
/** /**

View File

@@ -31,7 +31,6 @@ import android.annotation.SystemApi;
import android.annotation.SystemService; import android.annotation.SystemService;
import android.annotation.TestApi; import android.annotation.TestApi;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.companion.virtual.IVirtualDevice;
import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
@@ -971,17 +970,8 @@ public final class DisplayManager {
executor = new HandlerExecutor( executor = new HandlerExecutor(
Handler.createAsync(handler != null ? handler.getLooper() : Looper.myLooper())); Handler.createAsync(handler != null ? handler.getLooper() : Looper.myLooper()));
} }
return mGlobal.createVirtualDisplay(mContext, projection, null /* virtualDevice */, return mGlobal.createVirtualDisplay(mContext, projection, virtualDisplayConfig, callback,
virtualDisplayConfig, callback, executor, windowContext); 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);
} }
/** /**

View File

@@ -24,7 +24,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.PropertyInvalidatedCache; import android.app.PropertyInvalidatedCache;
import android.companion.virtual.IVirtualDevice;
import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context; import android.content.Context;
import android.content.pm.ParceledListSlice; import android.content.pm.ParceledListSlice;
@@ -586,18 +585,28 @@ public final class DisplayManagerGlobal {
} }
public VirtualDisplay createVirtualDisplay(@NonNull Context context, MediaProjection projection, public VirtualDisplay createVirtualDisplay(@NonNull Context context, MediaProjection projection,
IVirtualDevice virtualDevice, @NonNull VirtualDisplayConfig virtualDisplayConfig, @NonNull VirtualDisplayConfig virtualDisplayConfig, VirtualDisplay.Callback callback,
VirtualDisplay.Callback callback, @Nullable Executor executor, @Nullable Executor executor, @Nullable Context windowContext) {
@Nullable Context windowContext) {
VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, executor); VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, executor);
IMediaProjection projectionToken = projection != null ? projection.getProjection() : null; IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
int displayId; int displayId;
try { try {
displayId = mDm.createVirtualDisplay(virtualDisplayConfig, callbackWrapper, displayId = mDm.createVirtualDisplay(virtualDisplayConfig, callbackWrapper,
projectionToken, virtualDevice, context.getPackageName()); projectionToken, context.getPackageName());
} catch (RemoteException ex) { } catch (RemoteException ex) {
throw ex.rethrowFromSystemServer(); 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) { if (displayId < 0) {
Log.e(TAG, "Could not create virtual display: " + virtualDisplayConfig.getName()); Log.e(TAG, "Could not create virtual display: " + virtualDisplayConfig.getName());
return null; 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 VirtualDisplay.Callback mCallback;
@Nullable private final Executor mExecutor; @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 * @param executor The executor to call the {@code callback} on. Must not be {@code null} if
* the callback is not {@code null}. * the callback is not {@code null}.
*/ */
VirtualDisplayCallback(VirtualDisplay.Callback callback, Executor executor) { public VirtualDisplayCallback(VirtualDisplay.Callback callback, Executor executor) {
mCallback = callback; mCallback = callback;
mExecutor = mCallback != null ? Objects.requireNonNull(executor) : null; mExecutor = mCallback != null ? Objects.requireNonNull(executor) : null;
} }

View File

@@ -18,6 +18,7 @@ package android.hardware.display;
import android.annotation.IntDef; import android.annotation.IntDef;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.companion.virtual.IVirtualDevice;
import android.graphics.Point; import android.graphics.Point;
import android.hardware.SensorManager; import android.hardware.SensorManager;
import android.os.Handler; import android.os.Handler;
@@ -59,6 +60,14 @@ public abstract class DisplayManagerInternal {
public abstract void initPowerManagement(DisplayPowerCallbacks callbacks, public abstract void initPowerManagement(DisplayPowerCallbacks callbacks,
Handler handler, SensorManager sensorManager); 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. * Called by the power manager to request a new power state.
* <p> * <p>

View File

@@ -16,7 +16,6 @@
package android.hardware.display; package android.hardware.display;
import android.companion.virtual.IVirtualDevice;
import android.content.pm.ParceledListSlice; import android.content.pm.ParceledListSlice;
import android.graphics.Point; import android.graphics.Point;
import android.hardware.display.BrightnessConfiguration; import android.hardware.display.BrightnessConfiguration;
@@ -88,10 +87,10 @@ interface IDisplayManager {
void requestColorMode(int displayId, int colorMode); void requestColorMode(int displayId, int colorMode);
// Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate // 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, int createVirtualDisplay(in VirtualDisplayConfig virtualDisplayConfig,
in IVirtualDisplayCallback callback, in IMediaProjection projectionToken, in IVirtualDisplayCallback callback, in IMediaProjection projectionToken,
in IVirtualDevice virtualDevice, String packageName); String packageName);
// No permissions required, but must be same Uid as the creator. // No permissions required, but must be same Uid as the creator.
void resizeVirtualDisplay(in IVirtualDisplayCallback token, void resizeVirtualDisplay(in IVirtualDisplayCallback token,

View File

@@ -48,7 +48,6 @@ import com.android.internal.app.BlockedAppStreamingActivity;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer;
/** /**
@@ -66,6 +65,14 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
void onRunningAppsChanged(ArraySet<Integer> runningUids); 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 = private static final ComponentName BLOCKED_APP_STREAMING_COMPONENT =
new ComponentName("android", BlockedAppStreamingActivity.class.getName()); new ComponentName("android", BlockedAppStreamingActivity.class.getName());
@@ -89,7 +96,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
private final Object mGenericWindowPolicyControllerLock = new Object(); private final Object mGenericWindowPolicyControllerLock = new Object();
@ActivityPolicy @ActivityPolicy
private final int mDefaultActivityPolicy; private final int mDefaultActivityPolicy;
private final Consumer<ActivityInfo> mActivityBlockedCallback; private final ActivityBlockedCallback mActivityBlockedCallback;
private int mDisplayId = Display.INVALID_DISPLAY;
@NonNull @NonNull
@GuardedBy("mGenericWindowPolicyControllerLock") @GuardedBy("mGenericWindowPolicyControllerLock")
@@ -98,6 +106,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
private final Handler mHandler = new Handler(Looper.getMainLooper()); private final Handler mHandler = new Handler(Looper.getMainLooper());
private final ArraySet<RunningAppsChangedListener> mRunningAppsChangedListener = private final ArraySet<RunningAppsChangedListener> mRunningAppsChangedListener =
new ArraySet<>(); new ArraySet<>();
@Nullable
private final @AssociationRequest.DeviceProfile String mDeviceProfile; private final @AssociationRequest.DeviceProfile String mDeviceProfile;
/** /**
@@ -119,8 +128,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
* {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_ALLOWED} * {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_ALLOWED}
* @param defaultActivityPolicy Whether activities are default allowed to be displayed or * @param defaultActivityPolicy Whether activities are default allowed to be displayed or
* blocked. * blocked.
* @param activityListener Activity listener to listen for activity changes. The display ID * @param activityListener Activity listener to listen for activity changes.
* is not populated in this callback and is always {@link Display#INVALID_DISPLAY}.
* @param activityBlockedCallback Callback that is called when an activity is blocked from * @param activityBlockedCallback Callback that is called when an activity is blocked from
* launching. * launching.
* @param deviceProfile The {@link AssociationRequest.DeviceProfile} of this virtual device. * @param deviceProfile The {@link AssociationRequest.DeviceProfile} of this virtual device.
@@ -133,7 +141,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
@NonNull Set<ComponentName> blockedActivities, @NonNull Set<ComponentName> blockedActivities,
@ActivityPolicy int defaultActivityPolicy, @ActivityPolicy int defaultActivityPolicy,
@NonNull ActivityListener activityListener, @NonNull ActivityListener activityListener,
@NonNull Consumer<ActivityInfo> activityBlockedCallback, @NonNull ActivityBlockedCallback activityBlockedCallback,
@AssociationRequest.DeviceProfile String deviceProfile) { @AssociationRequest.DeviceProfile String deviceProfile) {
super(); super();
mAllowedUsers = allowedUsers; mAllowedUsers = allowedUsers;
@@ -148,6 +156,13 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
mDeviceProfile = deviceProfile; 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. */ /** Register a listener for running applications changes. */
public void registerRunningAppsChangedListener(@NonNull RunningAppsChangedListener listener) { public void registerRunningAppsChangedListener(@NonNull RunningAppsChangedListener listener) {
mRunningAppsChangedListener.add(listener); mRunningAppsChangedListener.add(listener);
@@ -169,7 +184,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
for (int i = 0; i < activityCount; i++) { for (int i = 0; i < activityCount; i++) {
final ActivityInfo aInfo = activities.get(i); final ActivityInfo aInfo = activities.get(i);
if (!canContainActivity(aInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) { if (!canContainActivity(aInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) {
mActivityBlockedCallback.accept(aInfo); mActivityBlockedCallback.onActivityBlocked(mDisplayId, aInfo);
return false; return false;
} }
} }
@@ -191,7 +206,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
} }
if (!canContainActivity(activityInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) { if (!canContainActivity(activityInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) {
mActivityBlockedCallback.accept(activityInfo); mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
return false; return false;
} }
@@ -201,14 +216,14 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
if (isNewTask && !mBlockedCrossTaskNavigations.isEmpty() if (isNewTask && !mBlockedCrossTaskNavigations.isEmpty()
&& mBlockedCrossTaskNavigations.contains(activityComponent)) { && mBlockedCrossTaskNavigations.contains(activityComponent)) {
Slog.d(TAG, "Virtual device blocking cross task navigation of " + activityComponent); Slog.d(TAG, "Virtual device blocking cross task navigation of " + activityComponent);
mActivityBlockedCallback.accept(activityInfo); mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
return false; return false;
} }
if (isNewTask && !mAllowedCrossTaskNavigations.isEmpty() if (isNewTask && !mAllowedCrossTaskNavigations.isEmpty()
&& !mAllowedCrossTaskNavigations.contains(activityComponent)) { && !mAllowedCrossTaskNavigations.contains(activityComponent)) {
Slog.d(TAG, "Virtual device not allowing cross task navigation of " Slog.d(TAG, "Virtual device not allowing cross task navigation of "
+ activityComponent); + activityComponent);
mActivityBlockedCallback.accept(activityInfo); mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
return false; return false;
} }
@@ -220,7 +235,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
public boolean keepActivityOnWindowFlagsChanged(ActivityInfo activityInfo, int windowFlags, public boolean keepActivityOnWindowFlagsChanged(ActivityInfo activityInfo, int windowFlags,
int systemWindowFlags) { int systemWindowFlags) {
if (!canContainActivity(activityInfo, windowFlags, systemWindowFlags)) { if (!canContainActivity(activityInfo, windowFlags, systemWindowFlags)) {
mActivityBlockedCallback.accept(activityInfo); mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
return false; return false;
} }
return true; return true;
@@ -234,7 +249,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
if (mActivityListener != null && topActivity != null) { if (mActivityListener != null && topActivity != null) {
// Post callback on the main thread so it doesn't block activity launching // Post callback on the main thread so it doesn't block activity launching
mHandler.post(() -> mHandler.post(() ->
mActivityListener.onTopActivityChanged(Display.INVALID_DISPLAY, topActivity)); mActivityListener.onTopActivityChanged(mDisplayId, topActivity));
} }
} }
@@ -245,7 +260,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
mRunningUids.addAll(runningUids); mRunningUids.addAll(runningUids);
if (mActivityListener != null && mRunningUids.isEmpty()) { if (mActivityListener != null && mRunningUids.isEmpty()) {
// Post callback on the main thread so it doesn't block activity launching // 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(() -> { mHandler.post(() -> {
@@ -257,7 +272,10 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
@Override @Override
public boolean canShowTasksInRecents() { 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) { switch (mDeviceProfile) {
case DEVICE_PROFILE_AUTOMOTIVE_PROJECTION: case DEVICE_PROFILE_AUTOMOTIVE_PROJECTION:
return false; return false;

View File

@@ -64,7 +64,6 @@ import android.util.SparseArray;
import android.view.Display; import android.view.Display;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.Toast; import android.widget.Toast;
import android.window.DisplayWindowPolicyController;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
@@ -110,11 +109,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
@GuardedBy("mVirtualDeviceLock") @GuardedBy("mVirtualDeviceLock")
private boolean mDefaultShowPointerIcon = true; private boolean mDefaultShowPointerIcon = true;
private ActivityListener createListenerAdapter(int displayId) { private ActivityListener createListenerAdapter() {
return new ActivityListener() { return new ActivityListener() {
@Override @Override
public void onTopActivityChanged(int unusedDisplayId, ComponentName topActivity) { public void onTopActivityChanged(int displayId, ComponentName topActivity) {
try { try {
mActivityListener.onTopActivityChanged(displayId, topActivity); mActivityListener.onTopActivityChanged(displayId, topActivity);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -123,7 +122,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
} }
@Override @Override
public void onDisplayEmpty(int unusedDisplayId) { public void onDisplayEmpty(int displayId) {
try { try {
mActivityListener.onDisplayEmpty(displayId); mActivityListener.onDisplayEmpty(displayId);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -529,24 +528,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
mInputController.dump(fout); mInputController.dump(fout);
} }
DisplayWindowPolicyController onVirtualDisplayCreatedLocked(int displayId) { GenericWindowPolicyController createWindowPolicyController() {
synchronized (mVirtualDeviceLock) { 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 = final GenericWindowPolicyController gwpc =
new GenericWindowPolicyController(FLAG_SECURE, new GenericWindowPolicyController(FLAG_SECURE,
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
@@ -556,19 +539,36 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
mParams.getAllowedActivities(), mParams.getAllowedActivities(),
mParams.getBlockedActivities(), mParams.getBlockedActivities(),
mParams.getDefaultActivityPolicy(), mParams.getDefaultActivityPolicy(),
createListenerAdapter(displayId), createListenerAdapter(),
activityInfo -> onActivityBlocked(displayId, activityInfo), this::onActivityBlocked,
mAssociationInfo.getDeviceProfile()); mAssociationInfo.getDeviceProfile());
gwpc.registerRunningAppsChangedListener(/* listener= */ this); gwpc.registerRunningAppsChangedListener(/* listener= */ this);
mWindowPolicyControllers.put(displayId, gwpc);
return gwpc; return gwpc;
} }
} }
void addWakeLockForDisplay(int displayId) { void onVirtualDisplayCreatedLocked(GenericWindowPolicyController gwpc, int displayId) {
synchronized (mVirtualDeviceLock) { synchronized (mVirtualDeviceLock) {
if (!mVirtualDisplayIds.contains(displayId) if (displayId == Display.INVALID_DISPLAY) {
|| mPerDisplayWakelocks.containsKey(displayId)) { 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); Slog.e(TAG, "Not creating wakelock for displayId " + displayId);
return; return;
} }
@@ -576,8 +576,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
PowerManager.WakeLock wakeLock = powerManager.newWakeLock( PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK, PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
TAG + ":" + displayId, displayId); TAG + ":" + displayId, displayId);
wakeLock.acquire();
mPerDisplayWakelocks.put(displayId, wakeLock); mPerDisplayWakelocks.put(displayId, wakeLock);
wakeLock.acquire();
} }
} }

View File

@@ -31,6 +31,10 @@ import android.companion.virtual.IVirtualDeviceManager;
import android.companion.virtual.VirtualDeviceManager; import android.companion.virtual.VirtualDeviceManager;
import android.companion.virtual.VirtualDeviceParams; import android.companion.virtual.VirtualDeviceParams;
import android.content.Context; 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.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
@@ -41,9 +45,9 @@ import android.util.ExceptionUtils;
import android.util.Slog; import android.util.Slog;
import android.util.SparseArray; import android.util.SparseArray;
import android.widget.Toast; import android.widget.Toast;
import android.window.DisplayWindowPolicyController;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils; import com.android.internal.util.DumpUtils;
import com.android.server.SystemService; import com.android.server.SystemService;
import com.android.server.companion.virtual.VirtualDeviceImpl.PendingTrampoline; import com.android.server.companion.virtual.VirtualDeviceImpl.PendingTrampoline;
@@ -203,6 +207,7 @@ public class VirtualDeviceManagerService extends SystemService {
} }
} }
@VisibleForTesting
class VirtualDeviceManagerImpl extends IVirtualDeviceManager.Stub implements class VirtualDeviceManagerImpl extends IVirtualDeviceManager.Stub implements
VirtualDeviceImpl.PendingTrampolineCallback { 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 @Nullable
private AssociationInfo getAssociationInfo(String packageName, int associationId) { private AssociationInfo getAssociationInfo(String packageName, int associationId) {
final int callingUserId = getCallingUserHandle().getIdentifier(); 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 @Override
public void onVirtualDisplayRemoved(IVirtualDevice virtualDevice, int displayId) { public void onVirtualDisplayRemoved(IVirtualDevice virtualDevice, int displayId) {
synchronized (mVirtualDeviceManagerLock) { synchronized (mVirtualDeviceManagerLock) {

View File

@@ -17,7 +17,6 @@
package com.android.server.companion.virtual; package com.android.server.companion.virtual;
import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDevice;
import android.window.DisplayWindowPolicyController;
/** /**
* Virtual device manager local service interface. * Virtual device manager local service interface.
@@ -30,17 +29,6 @@ public abstract class VirtualDeviceManagerInternal {
*/ */
public abstract boolean isValidVirtualDevice(IVirtualDevice virtualDevice); 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. * Notify a virtual display is removed.
* *

View File

@@ -1231,7 +1231,7 @@ public final class DisplayManagerService extends SystemService {
private int createVirtualDisplayInternal(VirtualDisplayConfig virtualDisplayConfig, private int createVirtualDisplayInternal(VirtualDisplayConfig virtualDisplayConfig,
IVirtualDisplayCallback callback, IMediaProjection projection, IVirtualDisplayCallback callback, IMediaProjection projection,
IVirtualDevice virtualDevice, String packageName) { IVirtualDevice virtualDevice, DisplayWindowPolicyController dwpc, String packageName) {
final int callingUid = Binder.getCallingUid(); final int callingUid = Binder.getCallingUid();
if (!validatePackageName(callingUid, packageName)) { if (!validatePackageName(callingUid, packageName)) {
throw new SecurityException("packageName must match the calling uid"); throw new SecurityException("packageName must match the calling uid");
@@ -1351,8 +1351,13 @@ public final class DisplayManagerService extends SystemService {
final long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity();
try { try {
synchronized (mSyncRoot) { synchronized (mSyncRoot) {
return createVirtualDisplayLocked(callback, projection, virtualDevice, callingUid, final int displayId = createVirtualDisplayLocked(callback, projection, callingUid,
packageName, surface, flags, virtualDisplayConfig); packageName, surface, flags, virtualDisplayConfig);
if (displayId != Display.INVALID_DISPLAY && virtualDevice != null && dwpc != null) {
mDisplayWindowPolicyControllers.put(displayId,
Pair.create(virtualDevice, dwpc));
}
return displayId;
} }
} finally { } finally {
Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token);
@@ -1360,8 +1365,7 @@ public final class DisplayManagerService extends SystemService {
} }
private int createVirtualDisplayLocked(IVirtualDisplayCallback callback, private int createVirtualDisplayLocked(IVirtualDisplayCallback callback,
IMediaProjection projection, IVirtualDevice virtualDevice, IMediaProjection projection, int callingUid, String packageName, Surface surface,
int callingUid, String packageName, Surface surface,
int flags, VirtualDisplayConfig virtualDisplayConfig) { int flags, VirtualDisplayConfig virtualDisplayConfig) {
if (mVirtualDisplayAdapter == null) { if (mVirtualDisplayAdapter == null) {
Slog.w(TAG, "Rejecting request to create private virtual display " 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); final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
if (display != null) { if (display != null) {
final int displayId = display.getDisplayIdLocked(); return 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;
} }
// Something weird happened and the logical display was not created. // Something weird happened and the logical display was not created.
@@ -3066,9 +3061,9 @@ public final class DisplayManagerService extends SystemService {
@Override // Binder call @Override // Binder call
public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig, public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
IVirtualDisplayCallback callback, IMediaProjection projection, IVirtualDisplayCallback callback, IMediaProjection projection,
IVirtualDevice virtualDeviceToken, String packageName) { String packageName) {
return createVirtualDisplayInternal(virtualDisplayConfig, callback, projection, return createVirtualDisplayInternal(virtualDisplayConfig, callback, projection,
virtualDeviceToken, packageName); null, null, packageName);
} }
@Override // Binder call @Override // Binder call
@@ -3534,7 +3529,8 @@ public final class DisplayManagerService extends SystemService {
return !Float.isNaN(refreshRate) && (refreshRate > 0.0f); return !Float.isNaN(refreshRate) && (refreshRate > 0.0f);
} }
private final class LocalService extends DisplayManagerInternal { @VisibleForTesting
final class LocalService extends DisplayManagerInternal {
@Override @Override
public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
@@ -3549,6 +3545,14 @@ public final class DisplayManagerService extends SystemService {
mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATIONS); 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 @Override
public boolean requestPowerState(int groupId, DisplayPowerRequest request, public boolean requestPowerState(int groupId, DisplayPowerRequest request,
boolean waitForNegativeProximity) { boolean waitForNegativeProximity) {

View File

@@ -228,36 +228,36 @@ public class VirtualDeviceManagerServiceTest {
@Test @Test
public void onVirtualDisplayRemovedLocked_doesNotThrowException() { public void onVirtualDisplayRemovedLocked_doesNotThrowException() {
final int displayId = 2; mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.onVirtualDisplayCreatedLocked(displayId); mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
// This call should not throw any exceptions. // This call should not throw any exceptions.
mDeviceImpl.onVirtualDisplayRemovedLocked(displayId); mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID);
} }
@Test @Test
public void onVirtualDisplayCreatedLocked_wakeLockIsAcquired() throws RemoteException { public void onVirtualDisplayCreatedLocked_wakeLockIsAcquired() throws RemoteException {
final int displayId = 2;
mDeviceImpl.onVirtualDisplayCreatedLocked(displayId);
verify(mIPowerManagerMock, never()).acquireWakeLock(any(Binder.class), anyInt(), verify(mIPowerManagerMock, never()).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class), nullable(String.class), nullable(String.class), nullable(WorkSource.class),
nullable(String.class), anyInt(), eq(null)); 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(), verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class), 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 @Test
public void onVirtualDisplayCreatedLocked_duplicateCalls_onlyOneWakeLockIsAcquired() public void onVirtualDisplayCreatedLocked_duplicateCalls_onlyOneWakeLockIsAcquired()
throws RemoteException { throws RemoteException {
final int displayId = 2; GenericWindowPolicyController gwpc = mDeviceImpl.createWindowPolicyController();
mDeviceImpl.onVirtualDisplayCreatedLocked(displayId); mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
assertThrows(IllegalStateException.class, assertThrows(IllegalStateException.class,
() -> mDeviceImpl.onVirtualDisplayCreatedLocked(displayId)); () -> mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID));
TestableLooper.get(this).processAllMessages(); TestableLooper.get(this).processAllMessages();
verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(), verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class), 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 @Test
@@ -269,30 +269,30 @@ public class VirtualDeviceManagerServiceTest {
@Test @Test
public void onVirtualDisplayRemovedLocked_wakeLockIsReleased() throws RemoteException { public void onVirtualDisplayRemovedLocked_wakeLockIsReleased() throws RemoteException {
final int displayId = 2; mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.onVirtualDisplayCreatedLocked(displayId); mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class); ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class);
TestableLooper.get(this).processAllMessages(); TestableLooper.get(this).processAllMessages();
verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(), verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(),
anyInt(), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class), 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(); IBinder wakeLock = wakeLockCaptor.getValue();
mDeviceImpl.onVirtualDisplayRemovedLocked(displayId); mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID);
verify(mIPowerManagerMock, Mockito.times(1)).releaseWakeLock(eq(wakeLock), anyInt()); verify(mIPowerManagerMock, Mockito.times(1)).releaseWakeLock(eq(wakeLock), anyInt());
} }
@Test @Test
public void addVirtualDisplay_displayNotReleased_wakeLockIsReleased() throws RemoteException { public void addVirtualDisplay_displayNotReleased_wakeLockIsReleased() throws RemoteException {
final int displayId = 2; mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.onVirtualDisplayCreatedLocked(displayId); mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class); ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class);
TestableLooper.get(this).processAllMessages(); TestableLooper.get(this).processAllMessages();
verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(), verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(),
anyInt(), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class), 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(); IBinder wakeLock = wakeLockCaptor.getValue();
// Close the VirtualDevice without first notifying it of the VirtualDisplay removal. // Close the VirtualDevice without first notifying it of the VirtualDisplay removal.
@@ -416,7 +416,8 @@ public class VirtualDeviceManagerServiceTest {
@Test @Test
public void onAudioSessionStarting_hasVirtualAudioController() { public void onAudioSessionStarting_hasVirtualAudioController() {
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback); mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback);
@@ -425,7 +426,8 @@ public class VirtualDeviceManagerServiceTest {
@Test @Test
public void onAudioSessionEnded_noVirtualAudioController() { public void onAudioSessionEnded_noVirtualAudioController() {
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback); mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback);
mDeviceImpl.onAudioSessionEnded(); mDeviceImpl.onAudioSessionEnded();
@@ -435,7 +437,8 @@ public class VirtualDeviceManagerServiceTest {
@Test @Test
public void close_cleanVirtualAudioController() { public void close_cleanVirtualAudioController() {
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback); mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback);
mDeviceImpl.close(); mDeviceImpl.close();
@@ -659,7 +662,8 @@ public class VirtualDeviceManagerServiceTest {
@Test @Test
public void openNonBlockedAppOnVirtualDisplay_doesNotStartBlockedAlertActivity() { public void openNonBlockedAppOnVirtualDisplay_doesNotStartBlockedAlertActivity() {
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get( GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID); DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any()); doNothing().when(mContext).startActivityAsUser(any(), any(), any());
@@ -677,7 +681,8 @@ public class VirtualDeviceManagerServiceTest {
@Test @Test
public void openPermissionControllerOnVirtualDisplay_startBlockedAlertActivity() { public void openPermissionControllerOnVirtualDisplay_startBlockedAlertActivity() {
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get( GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID); DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any()); doNothing().when(mContext).startActivityAsUser(any(), any(), any());
@@ -695,7 +700,8 @@ public class VirtualDeviceManagerServiceTest {
@Test @Test
public void openSettingsOnVirtualDisplay_startBlockedAlertActivity() { public void openSettingsOnVirtualDisplay_startBlockedAlertActivity() {
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get( GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID); DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any()); doNothing().when(mContext).startActivityAsUser(any(), any(), any());
@@ -713,7 +719,8 @@ public class VirtualDeviceManagerServiceTest {
@Test @Test
public void openVendingOnVirtualDisplay_startBlockedAlertActivity() { public void openVendingOnVirtualDisplay_startBlockedAlertActivity() {
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get( GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID); DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any()); doNothing().when(mContext).startActivityAsUser(any(), any(), any());
@@ -731,7 +738,8 @@ public class VirtualDeviceManagerServiceTest {
@Test @Test
public void openGoogleDialerOnVirtualDisplay_startBlockedAlertActivity() { public void openGoogleDialerOnVirtualDisplay_startBlockedAlertActivity() {
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get( GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID); DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any()); doNothing().when(mContext).startActivityAsUser(any(), any(), any());
@@ -749,7 +757,8 @@ public class VirtualDeviceManagerServiceTest {
@Test @Test
public void openGoogleMapsOnVirtualDisplay_startBlockedAlertActivity() { public void openGoogleMapsOnVirtualDisplay_startBlockedAlertActivity() {
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get( GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID); DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any()); doNothing().when(mContext).startActivityAsUser(any(), any(), any());

View File

@@ -45,6 +45,7 @@ import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.Curve; import android.hardware.display.Curve;
import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayViewport; import android.hardware.display.DisplayViewport;
import android.hardware.display.DisplayedContentSample; import android.hardware.display.DisplayedContentSample;
import android.hardware.display.DisplayedContentSamplingAttributes; import android.hardware.display.DisplayedContentSamplingAttributes;
@@ -63,6 +64,7 @@ import android.view.DisplayEventReceiver;
import android.view.DisplayInfo; import android.view.DisplayInfo;
import android.view.Surface; import android.view.Surface;
import android.view.SurfaceControl; import android.view.SurfaceControl;
import android.window.DisplayWindowPolicyController;
import androidx.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
@@ -220,7 +222,7 @@ public class DisplayManagerServiceTest {
builder.setUniqueId(uniqueId); builder.setUniqueId(uniqueId);
builder.setFlags(flags); builder.setFlags(flags);
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */, 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.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -346,7 +348,7 @@ public class DisplayManagerServiceTest {
builder.setFlags(flags); builder.setFlags(flags);
builder.setUniqueId(uniqueId); builder.setUniqueId(uniqueId);
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */, 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.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -586,8 +588,7 @@ public class DisplayManagerServiceTest {
VIRTUAL_DISPLAY_NAME, width, height, dpi); VIRTUAL_DISPLAY_NAME, width, height, dpi);
builder.setUniqueId(uniqueId); builder.setUniqueId(uniqueId);
final int firstDisplayId = binderService.createVirtualDisplay(builder.build(), final int firstDisplayId = binderService.createVirtualDisplay(builder.build(),
mMockAppToken /* callback */, null /* projection */, null /* virtualDeviceToken */, mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
PACKAGE_NAME);
// The second virtual display requests to mirror the first virtual display. // The second virtual display requests to mirror the first virtual display.
final String uniqueId2 = "uniqueId --- displayIdToMirrorTest #2"; final String uniqueId2 = "uniqueId --- displayIdToMirrorTest #2";
@@ -598,7 +599,7 @@ public class DisplayManagerServiceTest {
builder2.setDisplayIdToMirror(firstDisplayId); builder2.setDisplayIdToMirror(firstDisplayId);
final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(), final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(),
mMockAppToken2 /* callback */, null /* projection */, mMockAppToken2 /* callback */, null /* projection */,
null /* virtualDeviceToken */, PACKAGE_NAME); PACKAGE_NAME);
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class)); displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
// flush the handler // flush the handler
@@ -636,8 +637,7 @@ public class DisplayManagerServiceTest {
builder.setSurface(surface); builder.setSurface(surface);
builder.setUniqueId(uniqueId); builder.setUniqueId(uniqueId);
final int displayId = binderService.createVirtualDisplay(builder.build(), final int displayId = binderService.createVirtualDisplay(builder.build(),
mMockAppToken /* callback */, null /* projection */, null /* virtualDeviceToken */, mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
PACKAGE_NAME);
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class)); displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -669,7 +669,7 @@ public class DisplayManagerServiceTest {
builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP"); builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP");
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */, 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.performTraversalInternal(mock(SurfaceControl.Transaction.class));
displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */); displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId); DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
@@ -700,7 +700,7 @@ public class DisplayManagerServiceTest {
try { try {
bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */, 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 " fail("Creating virtual display with VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP without "
+ "ADD_TRUSTED_DISPLAY permission should throw SecurityException."); + "ADD_TRUSTED_DISPLAY permission should throw SecurityException.");
} catch (SecurityException e) { } catch (SecurityException e) {
@@ -716,6 +716,8 @@ public class DisplayManagerServiceTest {
public void testOwnDisplayGroup_allowCreationWithVirtualDevice() { public void testOwnDisplayGroup_allowCreationWithVirtualDevice() {
DisplayManagerService displayManager = DisplayManagerService displayManager =
new DisplayManagerService(mContext, mBasicInjector); new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerInternal localService = displayManager.new LocalService();
registerDefaultDisplays(displayManager); registerDefaultDisplays(displayManager);
DisplayManagerService.BinderService bs = displayManager.new BinderService(); DisplayManagerService.BinderService bs = displayManager.new BinderService();
@@ -733,8 +735,9 @@ public class DisplayManagerServiceTest {
when(mMockVirtualDeviceManagerInternal.isValidVirtualDevice(virtualDevice)) when(mMockVirtualDeviceManagerInternal.isValidVirtualDevice(virtualDevice))
.thenReturn(true); .thenReturn(true);
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */, int displayId = localService.createVirtualDisplay(builder.build(),
null /* projection */, virtualDevice /* virtualDeviceToken */, PACKAGE_NAME); mMockAppToken /* callback */, virtualDevice /* virtualDeviceToken */,
mock(DisplayWindowPolicyController.class), PACKAGE_NAME);
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class)); displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */); displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId); DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);