1
0
Fork 0
mirror of https://github.com/openstf/stf synced 2025-10-04 10:19:30 +02:00

Wake up and unlock device when it's being used. A bit messy, pending refactor.

This commit is contained in:
Simo Kinnunen 2014-03-04 18:00:31 +09:00
parent 999e5113bf
commit a25df0b293
6 changed files with 183 additions and 20 deletions

View file

@ -239,7 +239,7 @@ module.exports = function(options) {
.then(function(port) { .then(function(port) {
var log = logger.createLogger('device:inputAgent') var log = logger.createLogger('device:inputAgent')
return promiseutil.periodicNotify( return promiseutil.periodicNotify(
inputAgent.open(adb, options.serial) inputAgent.openAgent(adb, options.serial)
, 1000 , 1000
) )
.progressed(function() { .progressed(function() {
@ -264,8 +264,34 @@ module.exports = function(options) {
) )
}) })
}) })
.then(function(apk) {
log.info('Launching InputService')
return inputAgent.stopService(adb, options.serial)
.then(function() { .then(function() {
log.info('Launching input service') return devutil.waitForPortToFree(adb, options.serial, 1100)
})
.then(function(port) {
var log = logger.createLogger('device:inputService')
return inputAgent.openService(adb, options.serial)
.then(function() {
return promiseutil.periodicNotify(
devutil.waitForPort(adb, options.serial, port)
, 1000
)
.progressed(function() {
log.info('Waiting for InputService')
})
})
})
.then(function(conn) {
services.inputServiceSocket = vitals.register(
'device:inputService:socket'
, conn
)
})
})
.then(function() {
log.info('Launching TouchService')
return devutil.ensureUnusedPort(adb, options.serial, 2820) return devutil.ensureUnusedPort(adb, options.serial, 2820)
.then(function(port) { .then(function(port) {
var log = logger.createLogger('device:remote:input') var log = logger.createLogger('device:remote:input')
@ -290,7 +316,7 @@ module.exports = function(options) {
return monkey.connectStream(conn) return monkey.connectStream(conn)
}) })
.then(function(monkey) { .then(function(monkey) {
services.input = vitals.register( services.touch = vitals.register(
'device:remote:input:monkey' 'device:remote:input:monkey'
, Promise.promisifyAll(monkey) , Promise.promisifyAll(monkey)
) )
@ -404,25 +430,25 @@ module.exports = function(options) {
} }
}) })
.on(wire.TouchDownMessage, function(channel, message) { .on(wire.TouchDownMessage, function(channel, message) {
services.input.touchDownAsync(message.x, message.y) services.touch.touchDownAsync(message.x, message.y)
.catch(function(err) { .catch(function(err) {
log.error('touchDown failed', err.stack) log.error('touchDown failed', err.stack)
}) })
}) })
.on(wire.TouchMoveMessage, function(channel, message) { .on(wire.TouchMoveMessage, function(channel, message) {
services.input.touchMoveAsync(message.x, message.y) services.touch.touchMoveAsync(message.x, message.y)
.catch(function(err) { .catch(function(err) {
log.error('touchMove failed', err.stack) log.error('touchMove failed', err.stack)
}) })
}) })
.on(wire.TouchUpMessage, function(channel, message) { .on(wire.TouchUpMessage, function(channel, message) {
services.input.touchUpAsync(message.x, message.y) services.touch.touchUpAsync(message.x, message.y)
.catch(function(err) { .catch(function(err) {
log.error('touchUp failed', err.stack) log.error('touchUp failed', err.stack)
}) })
}) })
.on(wire.TapMessage, function(channel, message) { .on(wire.TapMessage, function(channel, message) {
services.input.tapAsync(message.x, message.y) services.touch.tapAsync(message.x, message.y)
.catch(function(err) { .catch(function(err) {
log.error('tap failed', err.stack) log.error('tap failed', err.stack)
}) })
@ -593,6 +619,8 @@ module.exports = function(options) {
)) ))
]) ])
services.logcat.on('entry', logcatListener) services.logcat.on('entry', logcatListener)
inputAgent.acquireWakeLock(services.inputServiceSocket)
inputAgent.unlock(services.inputServiceSocket)
owner = newOwner owner = newOwner
} }
@ -609,6 +637,8 @@ module.exports = function(options) {
)) ))
]) ])
services.logcat.removeListener('entry', logcatListener) services.logcat.removeListener('entry', logcatListener)
inputAgent.releaseWakeLock(services.inputServiceSocket)
inputAgent.lock(services.inputServiceSocket)
owner = null owner = null
} }

View file

@ -3,38 +3,106 @@ var util = require('util')
var Promise = require('bluebird') var Promise = require('bluebird')
var ProtoBuf = require('protobufjs') var ProtoBuf = require('protobufjs')
var ByteBuffer = require('protobufjs/node_modules/bytebuffer') var ByteBuffer = require('protobufjs/node_modules/bytebuffer')
var split = require('split') var semver = require('semver')
var pathutil = require('../util/pathutil') var pathutil = require('../util/pathutil')
var streamutil = require('../util/streamutil') var streamutil = require('../util/streamutil')
var SUPPORTED_VERSION = '~0.1.2';
var pkg = 'jp.co.cyberagent.stf.input.agent'
var apk = pathutil.vendor('InputAgent/InputAgent.apk')
var proto = ProtoBuf.loadProtoFile( var proto = ProtoBuf.loadProtoFile(
pathutil.vendor('InputAgent/inputAgentProtocol.proto') pathutil.vendor('InputAgent/proto/agent.proto')
).build().jp.co.cyberagent.stf.input.agent ).build().jp.co.cyberagent.stf.input.agent.proto
var inputAgent = module.exports = Object.create(null) var inputAgent = module.exports = Object.create(null)
inputAgent.open = function(adb, serial) { function IncompatibleVersionError(version) {
return adb.installAsync(serial, pathutil.vendor('InputAgent/InputAgent.apk')) Error.call(this, util.format('Incompatible version %s', version))
.then(function() { this.name = 'IncompatibleVersionError'
return adb.shellAsync(serial, 'pm path jp.co.cyberagent.stf.input.agent') this.version = version
}) Error.captureStackTrace(this, IncompatibleVersionError)
}
util.inherits(IncompatibleVersionError, Error)
inputAgent.IncompatibleVersionError = IncompatibleVersionError
inputAgent.getInstalledPath = function(adb, serial) {
return adb.shellAsync(serial, util.format("pm path '%s'", pkg))
.then(function(out) { .then(function(out) {
return streamutil.findLine(out, (/^package:/)) return streamutil.findLine(out, (/^package:/))
.then(function(line) { .then(function(line) {
return line.substr(8) return line.substr(8)
}) })
}) })
.then(function(apk) { }
inputAgent.ensureInstalled = function(adb, serial) {
return inputAgent.getInstalledPath(adb, serial)
.then(function(installedPath) {
return adb.shellAsync(serial, util.format(
"export CLASSPATH='%s';"
+ ' exec app_process /system/bin'
+ ' jp.co.cyberagent.stf.input.agent.InputAgent --version'
, installedPath
))
.then(function(out) {
return streamutil.readAll(out)
.then(function(buffer) {
var version = buffer.toString()
if (semver.satisfies(version, SUPPORTED_VERSION)) {
return installedPath
}
else {
return Promise.reject(new IncompatibleVersionError(version))
}
})
})
})
.catch(function() {
return adb.installAsync(serial, apk)
.then(function() {
return inputAgent.getInstalledPath(adb, serial)
})
})
}
inputAgent.openAgent = function(adb, serial) {
return inputAgent.ensureInstalled(adb, serial)
.then(function(installedPath) {
return adb.shellAsync(serial, util.format( return adb.shellAsync(serial, util.format(
"export CLASSPATH='%s';" "export CLASSPATH='%s';"
+ ' exec app_process /system/bin' + ' exec app_process /system/bin'
+ ' jp.co.cyberagent.stf.input.agent.InputAgent' + ' jp.co.cyberagent.stf.input.agent.InputAgent'
, apk , installedPath
)) ))
}) })
} }
inputAgent.openService = function(adb, serial) {
return inputAgent.ensureInstalled(adb, serial)
.then(function() {
var intent =
'-a jp.co.cyberagent.stf.input.agent.InputService.ACTION_START'
return adb.shellAsync(serial, util.format(
'am startservice --user 0 %s || am startservice %s'
, intent
, intent
))
})
}
inputAgent.stopService = function(adb, serial) {
var intent = '-a jp.co.cyberagent.stf.input.agent.InputService.ACTION_STOP'
return adb.shellAsync(serial, util.format(
'am startservice --user 0 %s || am startservice %s'
, intent
, intent
))
}
inputAgent.sendInputEvent = function(agent, event) { inputAgent.sendInputEvent = function(agent, event) {
var lengthBuffer = new ByteBuffer() var lengthBuffer = new ByteBuffer()
, messageBuffer = new proto.InputEvent(event).encode() , messageBuffer = new proto.InputEvent(event).encode()
@ -46,3 +114,23 @@ inputAgent.sendInputEvent = function(agent, event) {
, messageBuffer.toBuffer() , messageBuffer.toBuffer()
])) ]))
} }
inputAgent.unlock = function(service) {
service.write('unlock\n');
}
inputAgent.lock = function(service) {
service.write('lock\n');
}
inputAgent.acquireWakeLock = function(service) {
service.write('acquire wake lock\n');
}
inputAgent.releaseWakeLock = function(service) {
service.write('release wake lock\n');
}
inputAgent.identity = function(service, serial) {
service.write(util.format('show identity %s\n', serial));
}

View file

@ -91,6 +91,36 @@ devutil.waitForPort = function(adb, serial, port) {
}) })
} }
devutil.waitForPortToFree = function(adb, serial, port) {
function closedError(err) {
return err.message === 'closed'
}
return adb.openTcpAsync(serial, port)
.then(function(conn) {
var resolver = Promise.defer()
function endListener() {
resolver.resolve(port)
}
function errorListener(err) {
resolver.reject(err)
}
conn.on('end', endListener)
conn.on('error', errorListener)
return resolver.promise.finally(function() {
conn.removeListener('end', endListener)
conn.removeListener('error', errorListener)
conn.end()
})
})
.catch(closedError, function(err) {
return port
})
}
devutil.listPidsByComm = function(adb, serial, comm, bin) { devutil.listPidsByComm = function(adb, serial, comm, bin) {
var users = { var users = {
shell: true shell: true

View file

@ -1,6 +1,18 @@
var util = require('util')
var Promise = require('bluebird') var Promise = require('bluebird')
var split = require('split') var split = require('split')
function NoSuchLineError(message) {
Error.call(this, message)
this.name = 'NoSuchLineError'
Error.captureStackTrace(this, NoSuchLineError)
}
util.inherits(NoSuchLineError, Error)
module.exports.NoSuchLineError = NoSuchLineError
module.exports.readAll = function(stream) { module.exports.readAll = function(stream) {
var resolver = Promise.defer() var resolver = Promise.defer()
, collected = new Buffer(0) , collected = new Buffer(0)
@ -41,7 +53,7 @@ module.exports.findLine = function(stream, re) {
} }
function endListener() { function endListener() {
resolver.reject(new Error('No matching line found')) resolver.reject(new NoSuchLineError())
} }
function lineListener(line) { function lineListener(line) {

Binary file not shown.

View file

@ -1,15 +1,18 @@
package jp.co.cyberagent.stf.input.agent; package jp.co.cyberagent.stf.input.agent.proto;
option java_outer_classname = "AgentProto";
enum InputAction { enum InputAction {
KEYDOWN = 0; KEYDOWN = 0;
KEYUP = 1; KEYUP = 1;
KEYPRESS = 2; KEYPRESS = 2;
TYPE = 3; TYPE = 3;
WAKE = 4;
} }
message InputEvent { message InputEvent {
required InputAction action = 1; required InputAction action = 1;
required int32 keyCode = 2; optional int32 keyCode = 2;
optional bool shiftKey = 3; optional bool shiftKey = 3;
optional bool ctrlKey = 4; optional bool ctrlKey = 4;
optional bool altKey = 5; optional bool altKey = 5;