UNPKG

appium-uiautomator2-driver

Version:
110 lines 4.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseSurfaceFlingerDisplays = parseSurfaceFlingerDisplays; exports.mobileViewportScreenshot = mobileViewportScreenshot; exports.getViewportScreenshot = getViewportScreenshot; exports.getScreenshot = getScreenshot; exports.mobileScreenshots = mobileScreenshots; const support_1 = require("appium/support"); const utils_1 = require("../utils"); // Matches SurfaceFlinger output format: // Physical: Display 4619827259835644672 (HWC display 0): port=0 pnpId=GGL displayName="EMU_display_0" // Virtual: Display 11529215049243506835 (Virtual display): displayName="Emulator 2D Display" uniqueId="..." const DISPLAY_PATTERN = /^Display\s+(\d+)\s+\((?:HWC\s+display\s+(\d+)|Virtual\s+display)\):.*?displayName="([^"]*)"/gm; /** * Parses SurfaceFlinger display output to extract display information. * @param displaysInfo - The raw output from `adb shell dumpsys SurfaceFlinger --display-id` * @returns A record mapping display IDs to their information (without payload) */ function parseSurfaceFlingerDisplays(displaysInfo) { const infos = {}; const lines = displaysInfo.split('\n'); for (const line of lines) { let match; // Try to match display header line if ((match = DISPLAY_PATTERN.exec(line))) { const [, matchedDisplayId, hwcId, displayName] = match; // Skip match[0] (full match), then Display ID, HWC ID (optional), Display name // Determine if default: HWC display 0 is default, or first physical display if no HWC info const isDefault = hwcId !== undefined ? hwcId === '0' : !line.includes('Virtual') && Object.keys(infos).length === 0; infos[matchedDisplayId] = { id: matchedDisplayId, isDefault, name: displayName || undefined, }; // Reset regex lastIndex for next iteration DISPLAY_PATTERN.lastIndex = 0; } } return infos; } /** * Takes a screenshot of the current viewport */ async function mobileViewportScreenshot() { return await this.getViewportScreenshot(); } /** * Gets a screenshot of the current viewport */ async function getViewportScreenshot() { const screenshot = await this.getScreenshot(); const rect = await this.getViewPortRect(); return await support_1.imageUtil.cropBase64Image(screenshot, rect); } /** * Gets a screenshot of the current screen */ async function getScreenshot() { if (this.mjpegStream) { const data = await this.mjpegStream.lastChunkPNGBase64(); if (data) { return data; } this.log.warn('Tried to get screenshot from active MJPEG stream, but there ' + 'was no data yet. Falling back to regular screenshot methods.'); } return String(await this.uiautomator2.jwproxy.command('/screenshot', 'GET')); } /** * Retrieves screenshots of each display available to Android. * This functionality is only supported since Android 10. * @param displayId - Android display identifier to take a screenshot for. * If not provided then screenshots of all displays are going to be returned. * If no matches were found then an error is thrown. */ async function mobileScreenshots(displayId) { const displaysInfo = await this.adb.shell(['dumpsys', 'SurfaceFlinger', '--display-id']); const infos = parseSurfaceFlingerDisplays(displaysInfo); if ((0, utils_1.isEmpty)(infos)) { this.log.debug(displaysInfo); throw new Error('Cannot determine the information about connected Android displays'); } this.log.info(`Parsed Android display infos: ${JSON.stringify(infos)}`); const toB64Screenshot = async (dispId) => (await this.adb.takeScreenshot(dispId)).toString('base64'); const displayIdStr = displayId == null || displayId === '' ? null : String(displayId); if (displayIdStr) { if (!infos[displayIdStr]) { throw new Error(`The provided display identifier '${displayId}' is not known. ` + `Only the following displays have been detected: ${JSON.stringify(infos)}`); } return { [displayIdStr]: { ...infos[displayIdStr], payload: await toB64Screenshot(displayIdStr), }, }; } const allInfos = Object.values(infos).filter((info) => !!info?.id); const screenshots = await Promise.all(allInfos.map((info) => toB64Screenshot(info.id))); for (let i = 0; i < allInfos.length; i++) { const info = allInfos[i]; const payload = screenshots[i]; if (info && payload) { info.payload = payload; } } return infos; } //# sourceMappingURL=screenshot.js.map