diff --git a/lib/cli/device/index.js b/lib/cli/device/index.js index d2ad8a37fe..c4e9f37022 100644 --- a/lib/cli/device/index.js +++ b/lib/cli/device/index.js @@ -97,6 +97,12 @@ module.exports.builder = function(yargs) { , type: 'number' , default: process.env.SCREEN_JPEG_QUALITY || 80 }) + .option('screen-grabber', { + describe: 'The tool to be used for screen capture. ' + + 'Value must be either: minicap-bin (default) or minicap-apk' + , type: 'string' + , default: process.env.SCREEN_GRABBER || 'minicap-bin' + }) .option('screen-ping-interval', { describe: 'The interval at which to send ping messages to keep the ' + 'screen WebSocket alive.' @@ -159,6 +165,7 @@ module.exports.handler = function(argv) { , adbHost: argv.adbHost , adbPort: argv.adbPort , screenJpegQuality: argv.screenJpegQuality + , screenGrabber: argv.screenGrabber , screenPingInterval: argv.screenPingInterval , screenPort: argv.screenPort , screenWsUrlPattern: argv.screenWsUrlPattern diff --git a/lib/cli/provider/index.js b/lib/cli/provider/index.js index 32dd7b4af0..e9c189ed68 100644 --- a/lib/cli/provider/index.js +++ b/lib/cli/provider/index.js @@ -116,6 +116,12 @@ module.exports.builder = function(yargs) { , type: 'number' , default: process.env.SCREEN_JPEG_QUALITY || 80 }) + .option('screen-grabber', { + describe: 'The tool to be used for screen capture. ' + + 'Value must be either: minicap-bin (default) or minicap-apk' + , type: 'string' + , default: process.env.SCREEN_GRABBER || 'minicap-bin' + }) .option('screen-ping-interval', { describe: 'The interval at which to send ping messages to keep the ' + 'screen WebSocket alive.' diff --git a/lib/units/device/plugins/screen/capture.js b/lib/units/device/plugins/screen/capture.js index ea34dd8715..5e3040be82 100644 --- a/lib/units/device/plugins/screen/capture.js +++ b/lib/units/device/plugins/screen/capture.js @@ -33,7 +33,7 @@ module.exports = syrup.serial() log.info('Capturing screenshot') var file = util.format('/data/local/tmp/minicap_%d.jpg', Date.now()) - return minicap.run(util.format( + return minicap.run('minicap-apk', util.format( '-P %s -s >%s', projectionFormat(), file)) .then(adbkit.util.readAll) .then(function() { diff --git a/lib/units/device/plugins/screen/stream.js b/lib/units/device/plugins/screen/stream.js index 5d1bb88843..a12eadd0e9 100644 --- a/lib/units/device/plugins/screen/stream.js +++ b/lib/units/device/plugins/screen/stream.js @@ -25,8 +25,9 @@ module.exports = syrup.serial() .dependency(require('./options')) .define(function(options, adb, minicap, display, screenOptions) { var log = logger.createLogger('device:plugins:screen:stream') + log.info('ScreenGrabber option set to %s', options.screenGrabber) - function FrameProducer(config) { + function FrameProducer(config, grabber) { EventEmitter.call(this) this.actionQueue = [] this.runningState = FrameProducer.STATE_STOPPED @@ -37,6 +38,7 @@ module.exports = syrup.serial() this.banner = null this.parser = null this.frameConfig = config + this.grabber = options.screenGrabber this.readable = false this.needsReadable = false this.failCounter = new FailCounter(3, 10000) @@ -102,7 +104,7 @@ module.exports = syrup.serial() .catch(function(err) { return this._stop().finally(function() { this.failCounter.inc() - this.emit('error', err) + this.grabber = 'minicap-apk' }) }) .finally(function() { @@ -227,13 +229,13 @@ module.exports = syrup.serial() } FrameProducer.prototype._startService = function() { - log.info('Launching screen service') - return minicap.run(util.format( - '-S -Q %d -P %s' - , options.screenJpegQuality - , this.frameConfig.toString() - )) - .timeout(10000) + log.info('Launching screen service %s', this.grabber) + return minicap.run(this.grabber, util.format( + '-S -Q %d -P %s' + , options.screenJpegQuality + , this.frameConfig.toString() + )) + .timeout(10000) } FrameProducer.prototype._readOutput = function(out) { @@ -448,6 +450,7 @@ module.exports = syrup.serial() return createServer() .then(function(wss) { + log.info('creating FrameProducer: %s', options.screenGrabber) var frameProducer = new FrameProducer( new FrameConfig(display.properties, display.properties)) var broadcastSet = frameProducer.broadcastSet = new BroadcastSet() diff --git a/lib/units/device/resources/minicap.js b/lib/units/device/resources/minicap.js index 1b342b194f..2fc0c0e8c0 100644 --- a/lib/units/device/resources/minicap.js +++ b/lib/units/device/resources/minicap.js @@ -38,7 +38,7 @@ module.exports = syrup.serial() , lib: new Resource({ // @todo The lib ABI should match the bin ABI. Currently we don't // have an x86_64 version of the binary while the lib supports it. - src: pathutil.requiredMatch(abi.all.reduce(function(all, supportedAbi) { + src: pathutil.match(abi.all.reduce(function(all, supportedAbi) { return all.concat([ pathutil.module(util.format( '@devicefarmer/minicap-prebuilt/prebuilt/%s/lib/android-%s/minicap.so' @@ -59,6 +59,13 @@ module.exports = syrup.serial() , comm: 'minicap.so' // Not actually used for anything but log output , mode: 0755 }) + , apk: new Resource({ + src: pathutil.match([pathutil.module( + '@devicefarmer/minicap-prebuilt/prebuilt/noarch/minicap.apk')]) + , dest: ['/data/local/tmp/minicap.apk'] + , comm: 'minicap.apk' + , mode: 0755 + }) } function removeResource(res) { @@ -113,10 +120,15 @@ module.exports = syrup.serial() } function installAll() { - return Promise.all([ - installResource(resources.bin) - , installResource(resources.lib) - ]) + var resourcesToBeinstalled = [] + if(resources.lib.src !== undefined) { + resourcesToBeinstalled.push(installResource(resources.bin)) + resourcesToBeinstalled.push(installResource(resources.lib)) + } + if(resources.apk.src !== undefined) { + resourcesToBeinstalled.push(installResource(resources.apk)) + } + return Promise.all(resourcesToBeinstalled) } function stop() { @@ -135,13 +147,29 @@ module.exports = syrup.serial() return { bin: resources.bin.dest , lib: resources.lib.dest - , run: function(cmd) { - return adb.shell(options.serial, util.format( - 'LD_LIBRARY_PATH=%s exec %s %s' - , path.dirname(resources.lib.dest) - , resources.bin.dest - , cmd - )) + , apk: resources.apk.dest + , run: function(mode, cmd) { + var runCmd + if(mode === 'minicap-bin' && resources.lib.src !== undefined) { + runCmd = util.format( + 'LD_LIBRARY_PATH=%s exec %s %s' + , path.dirname(resources.lib.dest) + , resources.bin.dest + , cmd + ) + } + else if(mode === 'minicap-apk' && resources.apk.src !== undefined) { + runCmd = util.format( + 'CLASSPATH=%s app_process /system/bin io.devicefarmer.minicap.Main %s' + , resources.apk.dest + , cmd + ) + } + else { + log.error('Missing resources/unknown minicap grabber: %s', mode) + } + log.info(runCmd) + return adb.shell(options.serial, runCmd) } } }) diff --git a/lib/units/device/resources/service.js b/lib/units/device/resources/service.js index 6d9752ec32..8bb5b1d474 100644 --- a/lib/units/device/resources/service.js +++ b/lib/units/device/resources/service.js @@ -17,7 +17,7 @@ module.exports = syrup.serial() pathutil.vendor('STFService/wire.proto')) var resource = { - requiredVersion: '2.4.6' + requiredVersion: '2.4.7' , pkg: 'jp.co.cyberagent.stf' , main: 'jp.co.cyberagent.stf.Agent' , apk: pathutil.vendor('STFService/STFService.apk') diff --git a/lib/util/pathutil.js b/lib/util/pathutil.js index 5c2091c467..79c4a687d2 100644 --- a/lib/util/pathutil.js +++ b/lib/util/pathutil.js @@ -23,15 +23,25 @@ module.exports.module = function(target) { } // Export -module.exports.requiredMatch = function(candidates) { +module.exports.match = function(candidates) { for (var i = 0, l = candidates.length; i < l; ++i) { if (fs.existsSync(candidates[i])) { return candidates[i] } } + return undefined +} - throw new Error(util.format( - 'At least one of these paths should exist: %s' - , candidates.join(', ') - )) +// Export +module.exports.requiredMatch = function(candidates) { + var matched = this.match(candidates) + if(matched !== undefined) { + return matched + } + else { + throw new Error(util.format( + 'At least one of these paths should exist: %s' + , candidates.join(', ') + )) + } } diff --git a/package.json b/package.json index 476a7fd861..10c0238dc9 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "lodash": "^4.14.2", "markdown-serve": "^0.8.0", "mime": "^1.3.4", - "@devicefarmer/minicap-prebuilt": "^2.6.0", + "@devicefarmer/minicap-prebuilt": "^2.7.0", "minimatch": "^3.0.3", "@devicefarmer/minitouch-prebuilt": "^1.3.0", "my-local-ip": "^1.0.0", diff --git a/vendor/STFService/STFService.apk b/vendor/STFService/STFService.apk index ad8fbaf3ba..533b87eb7c 100644 Binary files a/vendor/STFService/STFService.apk and b/vendor/STFService/STFService.apk differ