Search code examples
androidadbscreenshotemulationandroid-multi-display

Take screenshot of virtual display of Android emulator (via ADB)


I am working with Android devices with multiple displays (physical devices and emulators) and want to take screenshots of each display through ADB. The problem that I have encountered is that whenever I have a virtual display on my emulator (the kind of display that you get when you create an extra display from the settings of the Android emulator by clicking on the three dots -> Displays -> Add secondary display), I cannot take a screenshot of it.

Next I'll explain how I go about this and the outputs that I am getting.

The screen capture command is adb shell screencap -d <display_id> sdcard/screenshot.png. I get my display IDs through adb shell dumpsys SurfaceFlinger --display-id (as is suggested by the screencap documentation). Another way in which I check how many displays I have is adb shell cmd display get-displays.

The output of adb shell cmd display get-displays is:

Displays:
  Display id 0: DisplayInfo{"Built-in Screen", displayId 0", displayGroupId 0, ..., type INTERNAL, uniqueId "local:4619827259835644672", ..., isValid=true
  Display id 2: DisplayInfo{"Emulator 2D Display", displayId 2", displayGroupId 0, ..., type VIRTUAL, uniqueId "virtual:com.android.emulator.multidisplay:1234562", ..., isValid=true
  Display id 3: DisplayInfo{"Emulator 2D Display", displayId 3", displayGroupId 0, ..., type VIRTUAL, uniqueId "virtual:com.android.emulator.multidisplay:1234563", ..., isValid=true

This sees all my displays (one main and two added displays) and gives me the uniqueIds that I have to feed to the screen capture command (here 4619827259835644672, 1234562, 1234563).

But the output of adb shell dumpsys SurfaceFlinger --display-id is:

Display 4619827259835644672 (HWC display 0): port=0 pnpId=GGL displayName="EMU_display_0"

This only sees the non-virtual displays. The two IDs of the virtual displays are missing.

Now the problem: I can only take a screenshot of the displays with the IDs that the SurfaceFlinger command sees. So 4619827259835644672 works, but the other two do not (I just get empty PNGs and error code 1 if I try to capture their screen). In other words, I cannot take screenshots of virtual emulator displays.

I have tried using a physical Android device with multiple displays and it works just fine because the extra displays were listed as type EXTERNAL. Both commands show all three displays in that case and I can take a screenshot of any of them.

Is there any other way of taking screenshots of virtual displays? Or am I doing something wrong?


Solution

  • To work with virtual display Id, use following command

    adb shell dumpsys SurfaceFlinger --displays
    

    This will show a 64bit virtual display id like

    ...
    Virtual Display 11529215050235899651
    ...
    

    Then use this number as an argument to the screencap

    adb shell screencap -d 11529215050235899651
    

    Keep in mind that display Ids for virtual displays are randomly assigned in every boot.

    However, not sure what device / OS version you are working with, but assuming your device is Android 14, there's a known bug that screencap doesn't work with virtual display Id. This was fixed in Android 15.