Skip to main content

framebuffer

Framebuffer command takes a high-quality, uncompressed screenshot of the device screen.

Framebuffer command is actually a wrapper for screencap executable, only uses binary output format instead of PNG. screencap changed its binary output format in Android 9, so it's difficult for a client to directly parse it without knowing the Android version first. Because framebuffer command is implemented in ADB daemon and shipped along with screencap on the device, it always knows the correct format.

Because the binary format contains raw RGB values, it's easier to parse than PNG. However, it's much larger than PNG thus requires more time to transfer and more memory to hold. If the client can decode PNG, it's recommended to use screencap command instead.

interface AdbFrameBuffer {
bpp: number;
colorSpace?: number;
size: number;
width: number;
height: number;
red_offset: number;
red_length: number;
blue_offset: number;
blue_length: number;
green_offset: number;
green_length: number;
alpha_offset: number;
alpha_length: number;
data: Uint8Array;
}

declare class Adb {
framebuffer(): Promise<AdbFrameBuffer>;
}

Color Space

On Android 9 and above, colorSpace field is present in the output. The values are:

  • 0: Unknown
  • 1: sRGB
  • 2: Display P3

Color Format

The four color_offset and color_length fields are numbers in bits. Some common color formats are presented by

fieldRGBA_8888RGBX_8888RGB_888RGB_565BGRA_8888
bpp3232241632
red_offset0001116
red_length88858
green_offset88858
green_length88868
blue_offset16161600
blue_length88858
alpha_offset24240024
alpha_length80008
note
  • I have only seen RGBA_8888 format
  • RGB_565 is actually BGR_565, but Android source code calls it RGB_565

Errors

declare abstract class AdbFrameBufferError extends Error {}

declare class AdbFrameBufferUnsupportedVersionError extends AdbFrameBufferError {}

declare class AdbFrameBufferForbiddenError extends AdbFrameBufferError {}

Framebuffer command has multiple versions, currently Tango supports version 1 and 2. If the device returns an unsupported version, an AdbFrameBufferUnsupportedVersionError will be thrown.

An AdbFrameBufferForbiddenError will be thrown when apps on the screen has disabled screen capture by setting the FLAG_SECURE flag on their windows. Lock screen, video streaming apps, and banking apps are common examples.

Examples

Take a screenshot

const screenshot = await adb.framebuffer();
Equivalent ADB Command
adb exec-out screencap -p > screenshot.png

Draw the screenshot to a canvas

Assume the screenshot has RGBA8888 color format:

const canvas = document.createElement("canvas");

canvas.width = screenshot.width;
canvas.height = screenshot.height;

const context = canvas.getContext("2d")!;
const imageData = new ImageData(
new Uint8ClampedArray(screenshot.data),
screenshot.width,
screenshot.height,
);
context.putImageData(imageData, 0, 0);

Save the canvas into a PNG file

const url = canvas.toDataURL();
const a = document.createElement("a");
a.href = url;
a.download = `screenshot.png`;
a.click();