appium-android-driver
Version:
Android UiAutomator and Chrome support for Appium
120 lines (119 loc) • 5.08 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.prepareEmulatorForImageInjection = prepareEmulatorForImageInjection;
exports.mobileInjectEmulatorCameraImage = mobileInjectEmulatorCameraImage;
const driver_1 = require("appium/driver");
const node_path_1 = __importDefault(require("node:path"));
const support_1 = require("@appium/support");
const node_crypto_1 = __importDefault(require("node:crypto"));
const lodash_1 = __importDefault(require("lodash"));
const EMULATOR_RESOURCES_ROOT = ['emulator', 'resources'];
const CONFIG_NAME = 'Toren1BD.posters';
const DEFAULT_CONFIG_PAYLOAD_PREFIX = `poster wall
size 2 2
position -0.807 0.320 5.316
rotation 0 -150 0
default poster.png
poster table`;
const DEFAULT_CONFIG_PAYLOAD = `${DEFAULT_CONFIG_PAYLOAD_PREFIX}
size 1 1
position 0 0 -1.5
rotation 0 0 0
`;
const PNG_MAGIC = '89504e47';
const PNG_MAGIC_LENGTH = 4;
/**
* Updates the emulator configuration to show the
* image using the given properties when one opens the Camera app.
*
* @this {AndroidDriver}
* @param {string} sdkRoot ADB SDK root folder path
* @returns {Promise<boolean>} If emulator services restart is needed
* to load the updated config or false if the current config is already up to date
* or does not need to be updated
*/
async function prepareEmulatorForImageInjection(sdkRoot) {
const { injectedImageProperties: props } = this.opts;
if (!props) {
return false;
}
const size = `size ${props.size?.scaleX ?? 1} ${props.size?.scaleY ?? 1}`;
const position = `position ${props.position?.x ?? 0} ${props.position?.y ?? 0} ${props.position?.z ?? -1.5}`;
const rotation = `rotation ${props.rotation?.x ?? 0} ${props.rotation?.y ?? 0} ${props.rotation?.z ?? 0}`;
const strProps = `${size}\n${position}\n${rotation}`;
const configPath = node_path_1.default.resolve(sdkRoot, ...EMULATOR_RESOURCES_ROOT, CONFIG_NAME);
if (await support_1.fs.exists(configPath)) {
const configPayload = await support_1.fs.readFile(configPath, 'utf8');
if (configPayload.includes(strProps)) {
this.log.info(`The image injection config at '${configPath}' is already up to date. Doing nothing`);
return false;
}
const updatedPayload = `${DEFAULT_CONFIG_PAYLOAD_PREFIX}
${size}
${position}
${rotation}
`;
await support_1.fs.writeFile(configPath, updatedPayload, 'utf-8');
}
else {
await support_1.fs.writeFile(configPath, DEFAULT_CONFIG_PAYLOAD, 'utf-8');
}
this.log.info(`The image injection config at '${configPath}' has been successfully updated with ` +
`${size}, ${position}, ${rotation}. ` +
`Expecting further emulator restart to reload the changed config.`);
return true;
}
/**
* Updates the emulator configuration to show the given
* image on the foreground when one opens the Camera app.
* It is expected that the rear camera of the emulator is
* configured to show VirtualScene for this feature to work.
* It is expected that the Virtual Scene posters config is
* already prepared and loaded either manually or using the
* `injectedImageProperties` capability.
*
* @this {AndroidDriver}
* @param {string} payload Base64-encoded payload of a .png image to be injected
* @returns {Promise<void>}
*/
async function mobileInjectEmulatorCameraImage(payload) {
if (!this.isEmulator()) {
throw new Error('The image injection feature is only available on emulators');
}
if (!lodash_1.default.isString(payload) || lodash_1.default.size(payload) <= PNG_MAGIC_LENGTH) {
throw new driver_1.errors.InvalidArgumentError(`You must provide a valid base64-encoded .PNG data as the 'payload' argument`);
}
const pngBuffer = Buffer.from(payload, 'base64');
const magic = pngBuffer.toString('hex', 0, PNG_MAGIC_LENGTH);
if (magic !== PNG_MAGIC) {
throw new driver_1.errors.InvalidArgumentError('The provided image payload must contain a valid base64-encoded .PNG data');
}
const tmpImagePath = await support_1.tempDir.path({
// this is needed to avoid creation of multiple temp files for the same image payload
prefix: calculateImageHash(pngBuffer),
suffix: '.png',
});
await support_1.fs.writeFile(tmpImagePath, pngBuffer);
await this.adb.execEmuConsoleCommand(`virtualscene-image table ${tmpImagePath}`);
this.log.info(`The provided image has been successully injected to the ${this.adb.curDeviceId} emulator`);
}
// #region Internal helpers
/**
*
* @param {Buffer} buffer
* @returns {string}
*/
function calculateImageHash(buffer) {
const hasher = node_crypto_1.default.createHash('sha1');
hasher.update(buffer);
return hasher.digest('hex');
}
// #endregion
/**
* @typedef {import('appium-adb').ADB} ADB
* @typedef {import('../driver').AndroidDriver} AndroidDriver
*/
//# sourceMappingURL=image-injection.js.map
;