Search code examples
androidapiuser-interfacedisplayandroid-virtualdisplay

Activity displays incorrect when launched on a secondary virtualdisplay


In my scenario, I want to mirror another app in my app.

I use DisplayManager to createVirtualDisplay for my SurfaceView. Then I set DisplayId as this VirtualDisplay in AcitivityOptions when I start activity.

By this process, another app can be launched successfully in my surfaceview. But there are some display problems. According to my test, only image, background color and GLSurfaceView.Renderer are rendered correctly. The ui-component such as TextView and Button are not rendered in SurfaceView.

From the above test result, I guess it may be related to the depth or order of rendering.

The example code is as followed:

SurfaceView surfaceView = findViewById(R.id.surface_view);
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION |
        DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC |
        DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;

DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
VirtualDisplay virtualDisplay = displayManager.createVirtualDisplay("MyVirtualDisplay",
        surfaceView.getWidth(), surfaceView.getHeight(), 1, surfaceView.getHolder().getSurface(),
        flags);

int displayId = virtualDisplay.getDisplay().getDisplayId();
ActivityOptions options = ActivityOptions.makeBasic().setLaunchDisplayId(displayId);

Intent intent = getPackageManager().getLaunchIntentForPackage(appName);
    intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(intent, options.toBundle());

By contrast, if I mirror same activity to a Display instead of VirtualDisplay, which can be captured by MediaRouter or DisplayManager. In this way, everything displays correctly (In my test, I simulate the second monitor by "Developer Options" -> "Simulate Secondary Displays"):

MediaRouter mediaRouter = (MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE);
MediaRouter.RouteInfo route = mediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
Display presentationDisplay = route.getPresentationDisplay();
int displayId = presentationDisplay.getDisplayId();

Intent intent = getPackageManager().getLaunchIntentForPackage(appName);
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
ActivityOptions options = ActivityOptions.makeBasic().setLaunchDisplayId(displayId);

startActivity(intent, options.toBundle());

Is there any process I miss or any flags I misconfigure in virtual display mode? Thanks for any help.

P.S. To mirror another app, I have rooted and launched as system app.


Solution

  • Your problem was calling createVirtualDisplay with wrong densityDpi, it should be more large numbers, such as 480, 560.