UNPKG

appium-adb-test

Version:

Android Debug Bridge interface

1,380 lines (1,080 loc) 85.5 kB
'use strict'; var _regeneratorRuntime = require('babel-runtime/regenerator')['default']; var _getIterator = require('babel-runtime/core-js/get-iterator')['default']; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; Object.defineProperty(exports, '__esModule', { value: true }); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _loggerJs = require('../logger.js'); var _loggerJs2 = _interopRequireDefault(_loggerJs); var _bluebird = require('bluebird'); var _bluebird2 = _interopRequireDefault(_bluebird); var _appiumSupport = require('appium-support'); var _helpers = require('../helpers'); var _teen_process = require('teen_process'); var _asyncbox = require('asyncbox'); var systemCallMethods = {}; var DEFAULT_ADB_EXEC_TIMEOUT = 20000; // in milliseconds systemCallMethods.getSdkBinaryPath = function callee$0$0(binaryName) { return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: _loggerJs2['default'].info('Checking whether ' + binaryName + ' is present'); if (!this.sdkRoot) { context$1$0.next = 5; break; } return context$1$0.abrupt('return', this.getBinaryFromSdkRoot(binaryName)); case 5: _loggerJs2['default'].warn('The ANDROID_HOME environment variable is not set to the Android SDK ' + 'root directory path. ANDROID_HOME is required for compatibility ' + ('with SDK 23+. Checking along PATH for ' + binaryName + '.')); context$1$0.next = 8; return _regeneratorRuntime.awrap(this.getBinaryFromPath(binaryName)); case 8: return context$1$0.abrupt('return', context$1$0.sent); case 9: case 'end': return context$1$0.stop(); } }, null, this); }; systemCallMethods.getCommandForOS = function () { var cmd = "which"; if (_appiumSupport.system.isWindows()) { cmd = "where"; } return cmd; }; systemCallMethods.getBinaryNameForOS = function (binaryName) { if (_appiumSupport.system.isWindows()) { if (binaryName === "android") { binaryName += ".bat"; } else { if (binaryName.indexOf(".exe", binaryName.length - 4) === -1) { binaryName += ".exe"; } } } return binaryName; }; systemCallMethods.getBinaryFromSdkRoot = function callee$0$0(binaryName) { var binaryLoc, binaryLocs, buildToolDirs, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, versionDir, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, loc, flag; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: binaryLoc = null; binaryName = this.getBinaryNameForOS(binaryName); binaryLocs = [_path2['default'].resolve(this.sdkRoot, "platform-tools", binaryName), _path2['default'].resolve(this.sdkRoot, "tools", binaryName)]; buildToolDirs = []; context$1$0.next = 6; return _regeneratorRuntime.awrap((0, _helpers.getDirectories)(_path2['default'].resolve(this.sdkRoot, "build-tools"))); case 6: buildToolDirs = context$1$0.sent; _iteratorNormalCompletion = true; _didIteratorError = false; _iteratorError = undefined; context$1$0.prev = 10; for (_iterator = _getIterator(buildToolDirs); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { versionDir = _step.value; binaryLocs.push(_path2['default'].resolve(this.sdkRoot, "build-tools", versionDir, binaryName)); } context$1$0.next = 18; break; case 14: context$1$0.prev = 14; context$1$0.t0 = context$1$0['catch'](10); _didIteratorError = true; _iteratorError = context$1$0.t0; case 18: context$1$0.prev = 18; context$1$0.prev = 19; if (!_iteratorNormalCompletion && _iterator['return']) { _iterator['return'](); } case 21: context$1$0.prev = 21; if (!_didIteratorError) { context$1$0.next = 24; break; } throw _iteratorError; case 24: return context$1$0.finish(21); case 25: return context$1$0.finish(18); case 26: _iteratorNormalCompletion2 = true; _didIteratorError2 = false; _iteratorError2 = undefined; context$1$0.prev = 29; _iterator2 = _getIterator(binaryLocs); case 31: if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) { context$1$0.next = 40; break; } loc = _step2.value; context$1$0.next = 35; return _regeneratorRuntime.awrap(_appiumSupport.fs.exists(loc)); case 35: flag = context$1$0.sent; if (flag) { binaryLoc = loc; } case 37: _iteratorNormalCompletion2 = true; context$1$0.next = 31; break; case 40: context$1$0.next = 46; break; case 42: context$1$0.prev = 42; context$1$0.t1 = context$1$0['catch'](29); _didIteratorError2 = true; _iteratorError2 = context$1$0.t1; case 46: context$1$0.prev = 46; context$1$0.prev = 47; if (!_iteratorNormalCompletion2 && _iterator2['return']) { _iterator2['return'](); } case 49: context$1$0.prev = 49; if (!_didIteratorError2) { context$1$0.next = 52; break; } throw _iteratorError2; case 52: return context$1$0.finish(49); case 53: return context$1$0.finish(46); case 54: if (!(binaryLoc === null)) { context$1$0.next = 56; break; } throw new Error('Could not find ' + binaryName + ' in tools, platform-tools, ' + ('or supported build-tools under ' + this.sdkRoot + ' ') + 'do you have the Android SDK installed at this location?'); case 56: binaryLoc = binaryLoc.trim(); _loggerJs2['default'].info('Using ' + binaryName + ' from ' + binaryLoc); return context$1$0.abrupt('return', binaryLoc); case 59: case 'end': return context$1$0.stop(); } }, null, this, [[10, 14, 18, 26], [19,, 21, 25], [29, 42, 46, 54], [47,, 49, 53]]); }; systemCallMethods.getBinaryFromPath = function callee$0$0(binaryName) { var binaryLoc, cmd, _ref, stdout; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: binaryLoc = null; cmd = this.getCommandForOS(); context$1$0.prev = 2; context$1$0.next = 5; return _regeneratorRuntime.awrap((0, _teen_process.exec)(cmd, [binaryName])); case 5: _ref = context$1$0.sent; stdout = _ref.stdout; _loggerJs2['default'].info('Using ' + binaryName + ' from ' + stdout); // TODO write a test for binaries with spaces. binaryLoc = stdout.trim(); return context$1$0.abrupt('return', binaryLoc); case 12: context$1$0.prev = 12; context$1$0.t0 = context$1$0['catch'](2); _loggerJs2['default'].errorAndThrow('Could not find ' + binaryName + ' Please set the ANDROID_HOME ' + 'environment variable with the Android SDK root directory path.'); case 15: case 'end': return context$1$0.stop(); } }, null, this, [[2, 12]]); }; systemCallMethods.getConnectedDevices = function callee$0$0() { var _ref2, stdout, startingIndex, devices, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, line, lineInfo; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: _loggerJs2['default'].debug("Getting connected devices..."); context$1$0.prev = 1; context$1$0.next = 4; return _regeneratorRuntime.awrap((0, _teen_process.exec)(this.executable.path, ['devices'])); case 4: _ref2 = context$1$0.sent; stdout = _ref2.stdout; startingIndex = stdout.indexOf("List of devices"); if (!(startingIndex === -1)) { context$1$0.next = 11; break; } throw new Error('Unexpected output while trying to get devices. output was: ' + stdout); case 11: // slicing ouput we care about. stdout = stdout.slice(startingIndex); devices = []; _iteratorNormalCompletion3 = true; _didIteratorError3 = false; _iteratorError3 = undefined; context$1$0.prev = 16; for (_iterator3 = _getIterator(stdout.split("\n")); !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { line = _step3.value; if (line.trim() !== "" && line.indexOf("List of devices") === -1 && line.indexOf("* daemon") === -1 && line.indexOf("offline") === -1) { lineInfo = line.split("\t"); // state is either "device" or "offline", afaict devices.push({ udid: lineInfo[0], state: lineInfo[1] }); } } context$1$0.next = 24; break; case 20: context$1$0.prev = 20; context$1$0.t0 = context$1$0['catch'](16); _didIteratorError3 = true; _iteratorError3 = context$1$0.t0; case 24: context$1$0.prev = 24; context$1$0.prev = 25; if (!_iteratorNormalCompletion3 && _iterator3['return']) { _iterator3['return'](); } case 27: context$1$0.prev = 27; if (!_didIteratorError3) { context$1$0.next = 30; break; } throw _iteratorError3; case 30: return context$1$0.finish(27); case 31: return context$1$0.finish(24); case 32: _loggerJs2['default'].debug(devices.length + ' device(s) connected'); return context$1$0.abrupt('return', devices); case 34: context$1$0.next = 39; break; case 36: context$1$0.prev = 36; context$1$0.t1 = context$1$0['catch'](1); _loggerJs2['default'].errorAndThrow('Error while getting connected devices. Original error: ' + context$1$0.t1.message); case 39: case 'end': return context$1$0.stop(); } }, null, this, [[1, 36], [16, 20, 24, 32], [25,, 27, 31]]); }; systemCallMethods.getDevicesWithRetry = function callee$0$0() { var timeoutMs = arguments.length <= 0 || arguments[0] === undefined ? 20000 : arguments[0]; var start, getDevices; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { var _this = this; while (1) switch (context$1$0.prev = context$1$0.next) { case 0: start = Date.now(); _loggerJs2['default'].debug("Trying to find a connected android device"); getDevices = function getDevices() { var devices; return _regeneratorRuntime.async(function getDevices$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: if (!(Date.now() - start > timeoutMs)) { context$2$0.next = 2; break; } throw new Error("Could not find a connected Android device."); case 2: context$2$0.prev = 2; context$2$0.next = 5; return _regeneratorRuntime.awrap(this.getConnectedDevices()); case 5: devices = context$2$0.sent; if (!(devices.length < 1)) { context$2$0.next = 15; break; } _loggerJs2['default'].debug("Could not find devices, restarting adb server..."); context$2$0.next = 10; return _regeneratorRuntime.awrap(this.restartAdb()); case 10: context$2$0.next = 12; return _regeneratorRuntime.awrap((0, _asyncbox.sleep)(200)); case 12: context$2$0.next = 14; return _regeneratorRuntime.awrap(getDevices()); case 14: return context$2$0.abrupt('return', context$2$0.sent); case 15: return context$2$0.abrupt('return', devices); case 18: context$2$0.prev = 18; context$2$0.t0 = context$2$0['catch'](2); _loggerJs2['default'].debug("Could not find devices, restarting adb server..."); context$2$0.next = 23; return _regeneratorRuntime.awrap(this.restartAdb()); case 23: context$2$0.next = 25; return _regeneratorRuntime.awrap((0, _asyncbox.sleep)(200)); case 25: context$2$0.next = 27; return _regeneratorRuntime.awrap(getDevices()); case 27: return context$2$0.abrupt('return', context$2$0.sent); case 28: case 'end': return context$2$0.stop(); } }, null, _this, [[2, 18]]); }; context$1$0.next = 5; return _regeneratorRuntime.awrap(getDevices()); case 5: return context$1$0.abrupt('return', context$1$0.sent); case 6: case 'end': return context$1$0.stop(); } }, null, this); }; systemCallMethods.restartAdb = function callee$0$0() { return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: if (this.suppressKillServer) { context$1$0.next = 10; break; } _loggerJs2['default'].debug('Restarting adb'); context$1$0.prev = 2; context$1$0.next = 5; return _regeneratorRuntime.awrap((0, _teen_process.exec)(this.executable.path, ['kill-server'])); case 5: context$1$0.next = 10; break; case 7: context$1$0.prev = 7; context$1$0.t0 = context$1$0['catch'](2); _loggerJs2['default'].error("Error killing ADB server, going to see if it's online anyway"); case 10: case 'end': return context$1$0.stop(); } }, null, this, [[2, 7]]); }; systemCallMethods.adbExec = function callee$0$0(cmd) { var opts = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; var execFunc; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { var _this2 = this; while (1) switch (context$1$0.prev = context$1$0.next) { case 0: if (cmd) { context$1$0.next = 2; break; } throw new Error("You need to pass in a command to adbExec()"); case 2: // setting default timeout for each command to prevent infinite wait. opts.timeout = opts.timeout || DEFAULT_ADB_EXEC_TIMEOUT; execFunc = function execFunc() { var linkerWarningRe, args, _ref3, stdout, protocolFaultError, deviceNotFoundError; return _regeneratorRuntime.async(function execFunc$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: linkerWarningRe = /^WARNING: linker.+$/m; context$2$0.prev = 1; if (!(cmd instanceof Array)) { cmd = [cmd]; } args = this.executable.defaultArgs.concat(cmd); _loggerJs2['default'].debug('Running \'' + this.executable.path + '\' with args: ' + ('' + JSON.stringify(args))); context$2$0.next = 7; return _regeneratorRuntime.awrap((0, _teen_process.exec)(this.executable.path, args, opts)); case 7: _ref3 = context$2$0.sent; stdout = _ref3.stdout; // sometimes ADB prints out stupid stdout warnings that we don't want // to include in any of the response data, so let's strip it out stdout = stdout.replace(linkerWarningRe, '').trim(); return context$2$0.abrupt('return', stdout); case 13: context$2$0.prev = 13; context$2$0.t0 = context$2$0['catch'](1); protocolFaultError = new RegExp("protocol fault \\(no status\\)", "i").test(context$2$0.t0); deviceNotFoundError = new RegExp("error: device ('.+' )?not found", "i").test(context$2$0.t0); if (!(protocolFaultError || deviceNotFoundError)) { context$2$0.next = 23; break; } _loggerJs2['default'].info('Error sending command, reconnecting device and retrying: ' + cmd); context$2$0.next = 21; return _regeneratorRuntime.awrap((0, _asyncbox.sleep)(1000)); case 21: context$2$0.next = 23; return _regeneratorRuntime.awrap(this.getDevicesWithRetry()); case 23: if (!context$2$0.t0.stdout) { context$2$0.next = 27; break; } stdout = context$2$0.t0.stdout; stdout = stdout.replace(linkerWarningRe, '').trim(); return context$2$0.abrupt('return', stdout); case 27: throw new Error('Error executing adbExec. Original error: \'' + context$2$0.t0.message + '\'; ' + ('Stderr: \'' + (context$2$0.t0.stderr || '').trim() + '\'; Code: \'' + context$2$0.t0.code + '\'')); case 28: case 'end': return context$2$0.stop(); } }, null, _this2, [[1, 13]]); }; context$1$0.next = 6; return _regeneratorRuntime.awrap((0, _asyncbox.retry)(2, execFunc)); case 6: return context$1$0.abrupt('return', context$1$0.sent); case 7: case 'end': return context$1$0.stop(); } }, null, this); }; systemCallMethods.shell = function callee$0$0(cmd) { var opts = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; var execCmd; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: context$1$0.next = 2; return _regeneratorRuntime.awrap(this.isDeviceConnected()); case 2: if (context$1$0.sent) { context$1$0.next = 4; break; } throw new Error('No device connected, cannot run adb shell command \'' + cmd.join(' ') + '\''); case 4: execCmd = ['shell']; if (cmd instanceof Array) { execCmd = execCmd.concat(cmd); } else { execCmd.push(cmd); } context$1$0.next = 8; return _regeneratorRuntime.awrap(this.adbExec(execCmd, opts)); case 8: return context$1$0.abrupt('return', context$1$0.sent); case 9: case 'end': return context$1$0.stop(); } }, null, this); }; systemCallMethods.createSubProcess = function () { var args = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0]; // add the default arguments args = this.executable.defaultArgs.concat(args); _loggerJs2['default'].debug('Creating ADB subprocess with args: ' + JSON.stringify(args)); return new _teen_process.SubProcess(this.getAdbPath(), args); }; // TODO can probably deprecate this now that the logic is just to read // this.adbPort systemCallMethods.getAdbServerPort = function () { return this.adbPort; }; systemCallMethods.getEmulatorPort = function callee$0$0() { var devices, port; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: _loggerJs2['default'].debug("Getting running emulator port"); if (!(this.emulatorPort !== null)) { context$1$0.next = 3; break; } return context$1$0.abrupt('return', this.emulatorPort); case 3: context$1$0.prev = 3; context$1$0.next = 6; return _regeneratorRuntime.awrap(this.getConnectedDevices()); case 6: devices = context$1$0.sent; port = this.getPortFromEmulatorString(devices[0].udid); if (!port) { context$1$0.next = 12; break; } return context$1$0.abrupt('return', port); case 12: throw new Error('Emulator port not found'); case 13: context$1$0.next = 18; break; case 15: context$1$0.prev = 15; context$1$0.t0 = context$1$0['catch'](3); _loggerJs2['default'].errorAndThrow('No devices connected. Original error: ' + context$1$0.t0.message); case 18: case 'end': return context$1$0.stop(); } }, null, this, [[3, 15]]); }; systemCallMethods.getPortFromEmulatorString = function (emStr) { var portPattern = /emulator-(\d+)/; if (portPattern.test(emStr)) { return parseInt(portPattern.exec(emStr)[1], 10); } return false; }; systemCallMethods.getConnectedEmulators = function callee$0$0() { var devices, emulators, _iteratorNormalCompletion4, _didIteratorError4, _iteratorError4, _iterator4, _step4, device, port; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: context$1$0.prev = 0; _loggerJs2['default'].debug("Getting connected emulators"); context$1$0.next = 4; return _regeneratorRuntime.awrap(this.getConnectedDevices()); case 4: devices = context$1$0.sent; emulators = []; _iteratorNormalCompletion4 = true; _didIteratorError4 = false; _iteratorError4 = undefined; context$1$0.prev = 9; for (_iterator4 = _getIterator(devices); !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { device = _step4.value; port = this.getPortFromEmulatorString(device.udid); if (port) { device.port = port; emulators.push(device); } } context$1$0.next = 17; break; case 13: context$1$0.prev = 13; context$1$0.t0 = context$1$0['catch'](9); _didIteratorError4 = true; _iteratorError4 = context$1$0.t0; case 17: context$1$0.prev = 17; context$1$0.prev = 18; if (!_iteratorNormalCompletion4 && _iterator4['return']) { _iterator4['return'](); } case 20: context$1$0.prev = 20; if (!_didIteratorError4) { context$1$0.next = 23; break; } throw _iteratorError4; case 23: return context$1$0.finish(20); case 24: return context$1$0.finish(17); case 25: _loggerJs2['default'].debug(emulators.length + ' emulator(s) connected'); return context$1$0.abrupt('return', emulators); case 29: context$1$0.prev = 29; context$1$0.t1 = context$1$0['catch'](0); _loggerJs2['default'].errorAndThrow('Error getting emulators. Original error: ' + context$1$0.t1.message); case 32: case 'end': return context$1$0.stop(); } }, null, this, [[0, 29], [9, 13, 17, 25], [18,, 20, 24]]); }; systemCallMethods.setEmulatorPort = function (emPort) { this.emulatorPort = emPort; }; systemCallMethods.setDeviceId = function (deviceId) { _loggerJs2['default'].debug('Setting device id to ' + deviceId); this.curDeviceId = deviceId; var argsHasDevice = this.executable.defaultArgs.indexOf('-s'); if (argsHasDevice !== -1) { // remove the old device id from the arguments this.executable.defaultArgs.splice(argsHasDevice, 2); } this.executable.defaultArgs.push('-s', deviceId); }; systemCallMethods.setDevice = function (deviceObj) { var deviceId = deviceObj.udid; var emPort = this.getPortFromEmulatorString(deviceId); this.setEmulatorPort(emPort); this.setDeviceId(deviceId); }; systemCallMethods.getRunningAVD = function callee$0$0(avdName) { var emulators, _iteratorNormalCompletion5, _didIteratorError5, _iteratorError5, _iterator5, _step5, emulator, runningAVDName; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: context$1$0.prev = 0; _loggerJs2['default'].debug('Trying to find ' + avdName + ' emulator'); context$1$0.next = 4; return _regeneratorRuntime.awrap(this.getConnectedEmulators()); case 4: emulators = context$1$0.sent; _iteratorNormalCompletion5 = true; _didIteratorError5 = false; _iteratorError5 = undefined; context$1$0.prev = 8; _iterator5 = _getIterator(emulators); case 10: if (_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done) { context$1$0.next = 23; break; } emulator = _step5.value; this.setEmulatorPort(emulator.port); context$1$0.next = 15; return _regeneratorRuntime.awrap(this.sendTelnetCommand("avd name")); case 15: runningAVDName = context$1$0.sent; if (!(avdName === runningAVDName)) { context$1$0.next = 20; break; } _loggerJs2['default'].debug('Found emulator ' + avdName + ' in port ' + emulator.port); this.setDeviceId(emulator.udid); return context$1$0.abrupt('return', emulator); case 20: _iteratorNormalCompletion5 = true; context$1$0.next = 10; break; case 23: context$1$0.next = 29; break; case 25: context$1$0.prev = 25; context$1$0.t0 = context$1$0['catch'](8); _didIteratorError5 = true; _iteratorError5 = context$1$0.t0; case 29: context$1$0.prev = 29; context$1$0.prev = 30; if (!_iteratorNormalCompletion5 && _iterator5['return']) { _iterator5['return'](); } case 32: context$1$0.prev = 32; if (!_didIteratorError5) { context$1$0.next = 35; break; } throw _iteratorError5; case 35: return context$1$0.finish(32); case 36: return context$1$0.finish(29); case 37: _loggerJs2['default'].debug('Emulator ' + avdName + ' not running'); return context$1$0.abrupt('return', null); case 41: context$1$0.prev = 41; context$1$0.t1 = context$1$0['catch'](0); _loggerJs2['default'].errorAndThrow('Error getting AVD. Original error: ' + context$1$0.t1.message); case 44: case 'end': return context$1$0.stop(); } }, null, this, [[0, 41], [8, 25, 29, 37], [30,, 32, 36]]); }; systemCallMethods.getRunningAVDWithRetry = function callee$0$0(avdName) { var timeoutMs = arguments.length <= 1 || arguments[1] === undefined ? 20000 : arguments[1]; var start, runningAVD; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: context$1$0.prev = 0; start = Date.now(); case 2: if (!(Date.now() - start < timeoutMs)) { context$1$0.next = 18; break; } context$1$0.prev = 3; context$1$0.next = 6; return _regeneratorRuntime.awrap(this.getRunningAVD(avdName.replace('@', ''))); case 6: runningAVD = context$1$0.sent; if (!runningAVD) { context$1$0.next = 9; break; } return context$1$0.abrupt('return', runningAVD); case 9: context$1$0.next = 14; break; case 11: context$1$0.prev = 11; context$1$0.t0 = context$1$0['catch'](3); // Do nothing. _loggerJs2['default'].info('Couldn\'t get running AVD, will retry. Error was: ' + context$1$0.t0.message); case 14: context$1$0.next = 16; return _regeneratorRuntime.awrap((0, _asyncbox.sleep)(200)); case 16: context$1$0.next = 2; break; case 18: _loggerJs2['default'].errorAndThrow('Could not find ' + avdName + ' emulator.'); context$1$0.next = 24; break; case 21: context$1$0.prev = 21; context$1$0.t1 = context$1$0['catch'](0); _loggerJs2['default'].errorAndThrow('Error getting AVD with retry. Original error: ' + context$1$0.t1.message); case 24: case 'end': return context$1$0.stop(); } }, null, this, [[0, 21], [3, 11]]); }; systemCallMethods.killAllEmulators = function callee$0$0() { var cmd, args; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: cmd = undefined, args = undefined; if (_appiumSupport.system.isWindows()) { cmd = 'TASKKILL'; args = ['TASKKILL', '/IM', 'emulator.exe']; } else { cmd = '/usr/bin/killall'; args = ['-m', 'emulator*']; } context$1$0.prev = 2; context$1$0.next = 5; return _regeneratorRuntime.awrap((0, _teen_process.exec)(cmd, args)); case 5: context$1$0.next = 10; break; case 7: context$1$0.prev = 7; context$1$0.t0 = context$1$0['catch'](2); _loggerJs2['default'].errorAndThrow('Error killing emulators. Original error: ' + context$1$0.t0.message); case 10: case 'end': return context$1$0.stop(); } }, null, this, [[2, 7]]); }; systemCallMethods.killEmulator = function callee$0$0(avdName) { var device; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: _loggerJs2['default'].debug('killing avd \'' + avdName + '\''); context$1$0.next = 3; return _regeneratorRuntime.awrap(this.getRunningAVD(avdName)); case 3: device = context$1$0.sent; if (!device) { context$1$0.next = 10; break; } context$1$0.next = 7; return _regeneratorRuntime.awrap(this.adbExec(['emu', 'kill'])); case 7: _loggerJs2['default'].info('successfully killed emulator \'' + avdName + '\''); context$1$0.next = 11; break; case 10: _loggerJs2['default'].info('no avd with name \'' + avdName + '\' running. skipping kill step.'); case 11: case 'end': return context$1$0.stop(); } }, null, this); }; systemCallMethods.launchAVD = function callee$0$0(avdName, avdArgs, language, country) { var avdLaunchTimeout = arguments.length <= 4 || arguments[4] === undefined ? 60000 : arguments[4]; var avdReadyTimeout = arguments.length <= 5 || arguments[5] === undefined ? 60000 : arguments[5]; var retryTimes = arguments.length <= 6 || arguments[6] === undefined ? 1 : arguments[6]; var emulatorBinaryPath, launchArgs, locale, proc; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: _loggerJs2['default'].debug('Launching Emulator with AVD ' + avdName + ', launchTimeout' + (avdLaunchTimeout + ' ms and readyTimeout ' + avdReadyTimeout + ' ms')); context$1$0.next = 3; return _regeneratorRuntime.awrap(this.getSdkBinaryPath("emulator")); case 3: emulatorBinaryPath = context$1$0.sent; if (avdName[0] === "@") { avdName = avdName.substr(1); } context$1$0.next = 7; return _regeneratorRuntime.awrap(this.checkAvdExist(avdName)); case 7: launchArgs = ["-avd", avdName]; if (typeof language === "string") { _loggerJs2['default'].debug('Setting Android Device Language to ' + language); launchArgs.push("-prop", 'persist.sys.language=' + language.toLowerCase()); } if (typeof country === "string") { _loggerJs2['default'].debug('Setting Android Device Country to ' + country); launchArgs.push("-prop", 'persist.sys.country=' + country.toUpperCase()); } locale = undefined; if (typeof language === "string" && typeof country === "string") { locale = language.toLowerCase() + "-" + country.toUpperCase(); } else if (typeof language === "string") { locale = language.toLowerCase(); } else if (typeof country === "string") { locale = country; } if (typeof locale === "string") { _loggerJs2['default'].debug('Setting Android Device Locale to ' + locale); launchArgs.push("-prop", 'persist.sys.locale=' + locale); } if (typeof avdArgs === "string") { avdArgs = avdArgs.split(" "); launchArgs = launchArgs.concat(avdArgs); } proc = new _teen_process.SubProcess(emulatorBinaryPath, launchArgs); context$1$0.next = 17; return _regeneratorRuntime.awrap(proc.start(0)); case 17: proc.on('output', function (stdout, stderr) { _loggerJs2['default'].info('[AVD OUTPUT] ' + (stdout || stderr)); }); context$1$0.next = 20; return _regeneratorRuntime.awrap((0, _asyncbox.retry)(retryTimes, this.getRunningAVDWithRetry.bind(this), avdName, avdLaunchTimeout)); case 20: context$1$0.next = 22; return _regeneratorRuntime.awrap(this.waitForEmulatorReady(avdReadyTimeout)); case 22: return context$1$0.abrupt('return', proc); case 23: case 'end': return context$1$0.stop(); } }, null, this); }; systemCallMethods.checkAvdExist = function callee$0$0(avdName) { var cmd, args, _ref4, stdout, existings; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: context$1$0.next = 2; return _regeneratorRuntime.awrap(this.getSdkBinaryPath('android')); case 2: cmd = context$1$0.sent; args = ['list', 'avd', '-c']; context$1$0.next = 6; return _regeneratorRuntime.awrap((0, _teen_process.exec)(cmd, args)); case 6: _ref4 = context$1$0.sent; stdout = _ref4.stdout; if (stdout.indexOf(avdName) === -1) { existings = '(' + stdout.trim().replace(/[\n]/g, '), (') + ')'; _loggerJs2['default'].errorAndThrow('Avd \'' + avdName + '\' is not available. please select your avd name from one of these: \'' + existings + '\''); } case 9: case 'end': return context$1$0.stop(); } }, null, this); }; systemCallMethods.waitForEmulatorReady = function callee$0$0() { var timeoutMs = arguments.length <= 0 || arguments[0] === undefined ? 20000 : arguments[0]; var start, stdout; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: start = Date.now(); _loggerJs2['default'].debug("Waiting until emulator is ready"); case 2: if (!(Date.now() - start < timeoutMs)) { context$1$0.next = 17; break; } context$1$0.prev = 3; context$1$0.next = 6; return _regeneratorRuntime.awrap(this.shell(["getprop", "init.svc.bootanim"])); case 6: stdout = context$1$0.sent; if (!(stdout.indexOf('stopped') > -1)) { context$1$0.next = 9; break; } return context$1$0.abrupt('return'); case 9: context$1$0.next = 13; break; case 11: context$1$0.prev = 11; context$1$0.t0 = context$1$0['catch'](3); case 13: context$1$0.next = 15; return _regeneratorRuntime.awrap((0, _asyncbox.sleep)(3000)); case 15: context$1$0.next = 2; break; case 17: _loggerJs2['default'].errorAndThrow('Emulator not ready'); case 18: case 'end': return context$1$0.stop(); } }, null, this, [[3, 11]]); }; systemCallMethods.waitForDevice = function callee$0$0() { var appDeviceReadyTimeout = arguments.length <= 0 || arguments[0] === undefined ? 30 : arguments[0]; var retries, timeout; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { var _this3 = this; while (1) switch (context$1$0.prev = context$1$0.next) { case 0: this.appDeviceReadyTimeout = appDeviceReadyTimeout; retries = 3; timeout = parseInt(this.appDeviceReadyTimeout, 10) / retries * 1000; context$1$0.next = 5; return _regeneratorRuntime.awrap((0, _asyncbox.retry)(retries, function callee$1$0() { return _regeneratorRuntime.async(function callee$1$0$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.prev = 0; context$2$0.next = 3; return _regeneratorRuntime.awrap(this.adbExec('wait-for-device', { timeout: timeout })); case 3: context$2$0.next = 5; return _regeneratorRuntime.awrap(this.ping()); case 5: context$2$0.next = 14; break; case 7: context$2$0.prev = 7; context$2$0.t0 = context$2$0['catch'](0); context$2$0.next = 11; return _regeneratorRuntime.awrap(this.restartAdb()); case 11: context$2$0.next = 13; return _regeneratorRuntime.awrap(this.getConnectedDevices()); case 13: _loggerJs2['default'].errorAndThrow('Error in waiting for device. Original error: \'' + context$2$0.t0.message + '\'. ' + 'Retrying by restarting ADB'); case 14: case 'end': return context$2$0.stop(); } }, null, _this3, [[0, 7]]); })); case 5: case 'end': return context$1$0.stop(); } }, null, this); }; systemCallMethods.reboot = function callee$0$0() { return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { var _this4 = this; while (1) switch (context$1$0.prev = context$1$0.next) { case 0: context$1$0.next = 2; return _regeneratorRuntime.awrap(this.shell(['stop'])); case 2: context$1$0.next = 4; return _regeneratorRuntime.awrap(_bluebird2['default'].delay(2000)); case 4: context$1$0.next = 6; return _regeneratorRuntime.awrap(this.setDeviceProperty('sys.boot_completed', 0)); case 6: context$1$0.next = 8; return _regeneratorRuntime.awrap(this.shell(['start'])); case 8: context$1$0.next = 10; return _regeneratorRuntime.awrap((0, _asyncbox.retryInterval)(90, 1000, function callee$1$0() { var booted; return _regeneratorRuntime.async(function callee$1$0$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.next = 2; return _regeneratorRuntime.awrap(this.getDeviceProperty('sys.boot_completed')); case 2: booted = context$2$0.sent; if (!(booted === '1')) { context$2$0.next = 7; break; } return context$2$0.abrupt('return'); case 7: _loggerJs2['default'].errorAndThrow('Waiting for reboot this takes time'); case 8: case 'end': return context$2$0.stop(); } }, null, _this4); })); case 10: case 'end': return context$1$0.stop(); } }, null, this); }; systemCallMethods.fileExists = function callee$0$0(remotePath) { var files; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: context$1$0.next = 2; return _regeneratorRuntime.awrap(this.ls(remotePath)); case 2: files = context$1$0.sent; return context$1$0.abrupt('return', files.length > 0); case 4: case 'end': return context$1$0.stop(); } }, null, this); }; systemCallMethods.ls = function callee$0$0(remotePath) { var stdout, lines; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: context$1$0.prev = 0; context$1$0.next = 3; return _regeneratorRuntime.awrap(this.shell(['ls', remotePath])); case 3: stdout = context$1$0.sent; lines = stdout.split("\n"); return context$1$0.abrupt('return', lines.map(function (l) { return l.trim(); }).filter(Boolean).filter(function (l) { return l.indexOf("No such file") === -1; })); case 8: context$1$0.prev = 8; context$1$0.t0 = context$1$0['catch'](0); if (!(context$1$0.t0.message.indexOf('No such file or directory') === -1)) { context$1$0.next = 12; break; } throw context$1$0.t0; case 12: return context$1$0.abrupt('return', []); case 13: case 'end': return context$1$0.stop(); } }, null, this, [[0, 8]]); }; exports['default'] = systemCallMethods; module.exports = exports['default']; // get subpaths for currently installed build tool directories // expecting adb devices to return output as // List of devices attached // emulator-5554 device // cool down // cool down // cool down // do nothing // let the emu finish stopping; //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi90b29scy9zeXN0ZW0tY2FsbHMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O29CQUFpQixNQUFNOzs7O3dCQUNQLGNBQWM7Ozs7d0JBQ2hCLFVBQVU7Ozs7NkJBQ0csZ0JBQWdCOzt1QkFDWixZQUFZOzs0QkFDVixjQUFjOzt3QkFDSCxVQUFVOztBQUd0RCxJQUFJLGlCQUFpQixHQUFHLEVBQUUsQ0FBQzs7QUFFM0IsSUFBTSx3QkFBd0IsR0FBRyxLQUFLLENBQUM7O0FBRXZDLGlCQUFpQixDQUFDLGdCQUFnQixHQUFHLG9CQUFnQixVQUFVOzs7O0FBQzdELDhCQUFJLElBQUksdUJBQXFCLFVBQVUsaUJBQWMsQ0FBQzs7YUFDbEQsSUFBSSxDQUFDLE9BQU87Ozs7OzRDQUNQLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLENBQUM7OztBQUU1Qyw4QkFBSSxJQUFJLENBQUMsMklBQ2tFLCtDQUN6QixVQUFVLE9BQUcsQ0FBQyxDQUFDOzt5Q0FDcEQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQzs7Ozs7Ozs7OztDQUdsRCxDQUFDOztBQUVGLGlCQUFpQixDQUFDLGVBQWUsR0FBRyxZQUFZO0FBQzlDLE1BQUksR0FBRyxHQUFHLE9BQU8sQ0FBQztBQUNsQixNQUFJLHNCQUFPLFNBQVMsRUFBRSxFQUFFO0FBQ3RCLE9BQUcsR0FBRyxPQUFPLENBQUM7R0FDZjtBQUNELFNBQU8sR0FBRyxDQUFDO0NBQ1osQ0FBQzs7QUFFRixpQkFBaUIsQ0FBQyxrQkFBa0IsR0FBRyxVQUFVLFVBQVUsRUFBRTtBQUMzRCxNQUFJLHNCQUFPLFNBQVMsRUFBRSxFQUFFO0FBQ3RCLFFBQUksVUFBVSxLQUFLLFNBQVMsRUFBRTtBQUM1QixnQkFBVSxJQUFJLE1BQU0sQ0FBQztLQUN0QixNQUFNO0FBQ0wsVUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMs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