constructor (opts = {}) { for (let req of REQD_PARAMS) { if (!opts || !opts[req]) { throw new Error(`Option '${req}' is required!`); } this[req] = opts[req]; } this.jwproxy = new JWProxy({host: this.host, port: this.systemPort}); this.proxyReqRes = this.jwproxy.proxyReqRes.bind(this.jwproxy); this.client = adbkit.createClient({ port: this.adb.adbPort, }); }
var Orng = function(serial, callback) { if (!(this instanceof Orng)) { return new Orng(serial, callback); } var orng = this; if (typeof serial === 'function') { callback = serial; serial = null; } this.client = adb.createClient(); this.client .listDevices() .then(function(devices) { if (!serial) { orng.deviceId = devices[0].id; } else { devices.forEach(function(device) { if (device.id === serial) { orng.deviceId = device.id; } }); } orng.client .getProperties(orng.deviceId) .then(function(properties) { var model = properties['ro.product.model']; orng.device = config.devices.b2g[model] || config.devices.android[model]; var densityProperty = orng.device.densityProperty || 'ro.sf.lcd_density'; orng.devicePixelRatio = properties[densityProperty] / 160; return orng.install(); }) .then(function() { callback.call(orng, orng); }); }); };
that.internalRun = function (config) { var adb = require('adbkit'), deviceClient = adb.createClient(), callbackarg = (config && "callback" in config ? config.callback : undefined), size = 0, counter = 0; if (typeof that.getId() === 'undefined' || that.getId() === 'all' || that.getId() === '') { console.log("run on all devices"); deviceClient.listDevices(function (err, devices) { if (err) { console.error("error listing devices " + err); that.error(err); that.addChildProcess({device: that, type: "android"}); callbackarg.call(that); } else { console.log("List of devices attached " + devices.length); size = (devices ? devices.length : 0); if (size) { devices.forEach(function (device) { that.addChildProcess({device: device, type: "android"}); runOnAndroid(that.getRunnerConfig(), device.id, that.getServerStarter(), deviceClient); counter++; if (counter < size) { callbackarg.call(that); } }); } else { that.error("List of devices attached " + devices.length); that.addChildProcess({device: that, type: "android"}); callbackarg.call(that); } } }); } else { that.addChildProcess({device: that, type: "android"}); runOnAndroid(that.getRunnerConfig(), that.getId(), that.getServerStarter(), deviceClient); callbackarg.call(that); } }
var $ = require('dombo'); var spawn = require('child_process').spawn; var Promise = require('bluebird'); var adb = require('adbkit'); var client = adb.createClient(); var fs = require('fs'); var StreamPng = require('StreamPng'); var serial = document.querySelector('#serial'); var command = document.querySelector('#command'); $('#ls-button').on('click', function () { console.log('ls'); list() }) $('#capture-button').on('click', function () { console.log('run ' + serial.value); screencap(serial.value); }) $('#command-button').on('click', function () { //console.log('run ' + serial.value); //run(command.value); run2(serial.value, command.value); //run2(serial.value, "pull /sdcard/tmp.mp4"); setTimeout(function (){ pull(serial.value, '/sdcard/tmp.mp4'); }, 1000); })
if (err) { console.log(' +', id, 'Unable to start KeepScreenOn'); } adbClient.startActivity(id, getBrowseIntent(url)); }); deviceIds[id] = true; fb.child(reportPath + 'clients/' + id).set(true); } function removeDevice(id) { console.log('-', id); delete deviceIds[id]; fb.child(reportPath + 'clients/' + id).remove(); } var adbClient = adb.createClient(); adbClient.trackDevices(function(err, tracker) { if (err) { console.log('*-*-*-* ADB Client Error', err); rebootPi('ADB Client error'); return; } tracker.on('add', function(device) { addDevice(device.id); }); tracker.on('remove', function(device) { removeDevice(device.id); }); tracker.on('change', function(device) { if (device.type === 'device') { addDevice(device.id);
module.exports = function(options) { var log = logger.createLogger('provider') var client = adb.createClient({ host: options.adbHost , port: options.adbPort }) var workers = {} var solo = wireutil.makePrivateChannel() var lists = { all: [] , ready: [] , waiting: [] } var totalsTimer // To make sure that we always bind the same type of service to the same // port, we must ensure that we allocate ports in fixed groups. var ports = options.ports.slice( 0 , options.ports.length - options.ports.length % 4 ) // Information about total devices var delayedTotals = (function() { function totals() { if (lists.waiting.length) { log.info( 'Providing %d of %d device(s); waiting for "%s"' , lists.ready.length , lists.all.length , lists.waiting.join('", "') ) delayedTotals() } else if (lists.ready.length < lists.all.length) { log.info( 'Providing all %d of %d device(s); ignoring "%s"' , lists.ready.length , lists.all.length , _.difference(lists.all, lists.ready).join('", "') ) } else { log.info( 'Providing all %d device(s)' , lists.all.length ) } } return function() { clearTimeout(totalsTimer) totalsTimer = setTimeout(totals, 10000) } })() // Output var push = zmqutil.socket('push') Promise.map(options.endpoints.push, function(endpoint) { return srv.resolve(endpoint).then(function(records) { return srv.attempt(records, function(record) { log.info('Sending output to "%s"', record.url) push.connect(record.url) return Promise.resolve(true) }) }) }) .catch(function(err) { log.fatal('Unable to connect to push endpoint', err) lifecycle.fatal() }) // Input var sub = zmqutil.socket('sub') Promise.map(options.endpoints.sub, function(endpoint) { return srv.resolve(endpoint).then(function(records) { return srv.attempt(records, function(record) { log.info('Receiving input from "%s"', record.url) sub.connect(record.url) return Promise.resolve(true) }) }) }) .catch(function(err) { log.fatal('Unable to connect to sub endpoint', err) lifecycle.fatal() }) // Establish always-on channels ;[solo].forEach(function(channel) { log.info('Subscribing to permanent channel "%s"', channel) sub.subscribe(channel) }) // Track and manage devices client.trackDevices().then(function(tracker) { log.info('Tracking devices') // This can happen when ADB doesn't have a good connection to // the device function isWeirdUnusableDevice(device) { return device.id === '????????????' } // Check whether the device is remote (i.e. if we're connecting to // an IP address (or hostname) and port pair). function isRemoteDevice(device) { return device.id.indexOf(':') !== -1 } // Helper for ignoring unwanted devices function filterDevice(listener) { return function(device) { if (isWeirdUnusableDevice(device)) { log.warn('ADB lists a weird device: "%s"', device.id) return false } if (!options.allowRemote && isRemoteDevice(device)) { log.info( 'Filtered out remote device "%s", use --allow-remote to override' , device.id ) return false } if (options.filter && !options.filter(device)) { log.info('Filtered out device "%s"', device.id) return false } return listener(device) } } // To make things easier, we're going to cheat a little, and make all // device events go to their own EventEmitters. This way we can keep all // device data in the same scope. var flippedTracker = new EventEmitter() tracker.on('add', filterDevice(function(device) { log.info('Found device "%s" (%s)', device.id, device.type) var privateTracker = new EventEmitter() var willStop = false var timer, worker // Wait for others to acknowledge the device var register = new Promise(function(resolve) { // Tell others we found a device push.send([ wireutil.global , wireutil.envelope(new wire.DeviceIntroductionMessage( device.id , wireutil.toDeviceStatus(device.type) , new wire.ProviderMessage( solo , options.name ) )) ]) privateTracker.once('register', resolve) }) // Spawn a device worker function spawn() { var allocatedPorts = ports.splice(0, 4) var proc = options.fork(device, allocatedPorts.slice()) var resolver = Promise.defer() function exitListener(code, signal) { if (signal) { log.warn( 'Device worker "%s" was killed with signal %s, assuming ' + 'deliberate action and not restarting' , device.id , signal ) resolver.resolve() } else if (code === 0) { log.info('Device worker "%s" stopped cleanly', device.id) resolver.resolve() } else { resolver.reject(new procutil.ExitError(code)) } } function errorListener(err) { log.error( 'Device worker "%s" had an error: %s' , device.id , err.message ) } function messageListener(message) { switch (message) { case 'ready': _.pull(lists.waiting, device.id) lists.ready.push(device.id) break default: log.warn( 'Unknown message from device worker "%s": "%s"' , device.id , message ) break } } proc.on('exit', exitListener) proc.on('error', errorListener) proc.on('message', messageListener) lists.waiting.push(device.id) return resolver.promise .cancellable() .finally(function() { log.info('Cleaning up device worker "%s"', device.id) proc.removeListener('exit', exitListener) proc.removeListener('error', errorListener) proc.removeListener('message', messageListener) // Return used ports to the main pool Array.prototype.push.apply(ports, allocatedPorts) // Update lists _.pull(lists.ready, device.id) _.pull(lists.waiting, device.id) }) .catch(Promise.CancellationError, function() { log.info('Gracefully killing device worker "%s"', device.id) return procutil.gracefullyKill(proc, options.killTimeout) }) .catch(Promise.TimeoutError, function(err) { log.error( 'Device worker "%s" did not stop in time: %s' , device.id , err.message ) }) } // Starts a device worker and keeps it alive function work() { return (worker = workers[device.id] = spawn()) .then(function() { log.info('Device worker "%s" has retired', device.id) delete workers[device.id] worker = null // Tell others the device is gone push.send([ wireutil.global , wireutil.envelope(new wire.DeviceAbsentMessage( device.id )) ]) }) .catch(procutil.ExitError, function(err) { if (!willStop) { log.error( 'Device worker "%s" died with code %s' , device.id , err.code ) log.info('Restarting device worker "%s"', device.id) return Promise.delay(500) .then(function() { return work() }) } }) } // No more work required function stop() { if (worker) { log.info('Shutting down device worker "%s"', device.id) worker.cancel() } } // Check if we can do anything with the device function check() { clearTimeout(timer) if (device.present) { // We might get multiple status updates in rapid succession, // so let's wait for a while switch (device.type) { case 'device': case 'emulator': willStop = false timer = setTimeout(work, 100) break default: willStop = true timer = setTimeout(stop, 100) break } } else { stop() } } register.then(function() { log.info('Registered device "%s"', device.id) check() }) // Statistics lists.all.push(device.id) delayedTotals() // Will be set to false when the device is removed _.assign(device, { present: true }) // When any event occurs on the added device function deviceListener(type, updatedDevice) { // Okay, this is a bit unnecessary but it allows us to get rid of an // ugly switch statement and return to the original style. privateTracker.emit(type, updatedDevice) } // When the added device changes function changeListener(updatedDevice) { register.then(function() { log.info( 'Device "%s" is now "%s" (was "%s")' , device.id , updatedDevice.type , device.type ) _.assign(device, { type: updatedDevice.type }) // Tell others the device changed push.send([ wireutil.global , wireutil.envelope(new wire.DeviceStatusMessage( device.id , wireutil.toDeviceStatus(device.type) )) ]) check() }) } // When the added device gets removed function removeListener() { register.then(function() { log.info('Lost device "%s" (%s)', device.id, device.type) clearTimeout(timer) flippedTracker.removeListener(device.id, deviceListener) _.pull(lists.all, device.id) delayedTotals() // Tell others the device is gone push.send([ wireutil.global , wireutil.envelope(new wire.DeviceAbsentMessage( device.id )) ]) _.assign(device, { present: false }) check() }) } flippedTracker.on(device.id, deviceListener) privateTracker.on('change', changeListener) privateTracker.on('remove', removeListener) })) tracker.on('change', filterDevice(function(device) { flippedTracker.emit(device.id, 'change', device) })) tracker.on('remove', filterDevice(function(device) { flippedTracker.emit(device.id, 'remove', device) })) sub.on('message', wirerouter() .on(wire.DeviceRegisteredMessage, function(channel, message) { flippedTracker.emit(message.serial, 'register') }) .handler()) lifecycle.share('Tracker', tracker) }) lifecycle.observe(function() { [push, sub].forEach(function(sock) { try { sock.close() } catch (err) { // No-op } }) clearTimeout(totalsTimer) return Promise.all(Object.keys(workers).map(function(serial) { return workers[serial].cancel() })) }) }
constructor(options) { this.client = adb.createClient(); this.id = get(options, 'chrome.android.deviceSerial'); this.port = options.devToolsPort; }