mirror of
https://github.com/DeviceFarmer/stf.git
synced 2026-04-18 16:13:24 +02:00
Refactor InputAgent into STFService. Support copypasting (only pasting implemented in the UI right now though).
This commit is contained in:
70
lib/roles/device/plugins/clipboard.js
Normal file
70
lib/roles/device/plugins/clipboard.js
Normal file
@@ -0,0 +1,70 @@
|
||||
var syrup = require('syrup')
|
||||
|
||||
var logger = require('../../../util/logger')
|
||||
var wire = require('../../../wire')
|
||||
var wireutil = require('../../../wire/util')
|
||||
|
||||
module.exports = syrup.serial()
|
||||
.dependency(require('../support/router'))
|
||||
.dependency(require('../support/push'))
|
||||
.dependency(require('./input'))
|
||||
.define(function(options, router, push, input) {
|
||||
var log = logger.createLogger('device:plugins:clipboard')
|
||||
|
||||
router.on(wire.PasteMessage, function(channel, message) {
|
||||
log.info('Pasting "%s" to clipboard', message.text)
|
||||
var seq = 0
|
||||
input.paste(message.text)
|
||||
.then(function() {
|
||||
push.send([
|
||||
channel
|
||||
, wireutil.envelope(new wire.TransactionDoneMessage(
|
||||
options.serial
|
||||
, seq++
|
||||
, true
|
||||
))
|
||||
])
|
||||
})
|
||||
.catch(function(err) {
|
||||
log.error('Paste failed', err.stack)
|
||||
push.send([
|
||||
channel
|
||||
, wireutil.envelope(new wire.TransactionDoneMessage(
|
||||
options.serial
|
||||
, seq++
|
||||
, false
|
||||
, err.message
|
||||
))
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
router.on(wire.CopyMessage, function(channel) {
|
||||
log.info('Copying clipboard contents')
|
||||
var seq = 0
|
||||
input.copy()
|
||||
.then(function(content) {
|
||||
push.send([
|
||||
channel
|
||||
, wireutil.envelope(new wire.TransactionDoneMessage(
|
||||
options.serial
|
||||
, seq++
|
||||
, true
|
||||
, content
|
||||
))
|
||||
])
|
||||
})
|
||||
.catch(function(err) {
|
||||
log.error('Copy failed', err.stack)
|
||||
push.send([
|
||||
channel
|
||||
, wireutil.envelope(new wire.TransactionDoneMessage(
|
||||
options.serial
|
||||
, seq++
|
||||
, false
|
||||
, err.message
|
||||
))
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -2,7 +2,7 @@ var util = require('util')
|
||||
|
||||
var syrup = require('syrup')
|
||||
var split = require('split')
|
||||
var ByteBuffer = require('protobufjs/node_modules/bytebuffer')
|
||||
var Promise = require('bluebird')
|
||||
|
||||
var wire = require('../../../wire')
|
||||
var wireutil = require('../../../wire/util')
|
||||
@@ -10,26 +10,29 @@ var devutil = require('../../../util/devutil')
|
||||
var keyutil = require('../../../util/keyutil')
|
||||
var streamutil = require('../../../util/streamutil')
|
||||
var logger = require('../../../util/logger')
|
||||
var ms = require('../../../wire/messagestream')
|
||||
|
||||
module.exports = syrup.serial()
|
||||
.dependency(require('../support/adb'))
|
||||
.dependency(require('../support/router'))
|
||||
.dependency(require('../support/push'))
|
||||
.dependency(require('../support/quit'))
|
||||
.dependency(require('../resources/inputagent'))
|
||||
.dependency(require('../resources/service'))
|
||||
.define(function(options, adb, router, push, quit, apk) {
|
||||
var log = logger.createLogger('device:plugins:input')
|
||||
var serviceQueue = []
|
||||
|
||||
var agent = {
|
||||
socket: null
|
||||
, writer: null
|
||||
, port: 1090
|
||||
}
|
||||
|
||||
var service = {
|
||||
socket: null
|
||||
, writer: null
|
||||
, reader: null
|
||||
, port: 1100
|
||||
, startAction: 'jp.co.cyberagent.stf.input.agent.InputService.ACTION_START'
|
||||
, stopAction: 'jp.co.cyberagent.stf.input.agent.InputService.ACTION_STOP'
|
||||
}
|
||||
|
||||
function openAgent() {
|
||||
@@ -40,8 +43,7 @@ module.exports = syrup.serial()
|
||||
})
|
||||
.then(function() {
|
||||
return adb.shell(options.serial, util.format(
|
||||
"export CLASSPATH='%s';" +
|
||||
" exec app_process /system/bin '%s'"
|
||||
"export CLASSPATH='%s'; exec app_process /system/bin '%s'"
|
||||
, apk.path
|
||||
, apk.main
|
||||
))
|
||||
@@ -65,6 +67,8 @@ module.exports = syrup.serial()
|
||||
})
|
||||
.then(function(conn) {
|
||||
agent.socket = conn
|
||||
agent.writer = new ms.DelimitingStream()
|
||||
agent.writer.pipe(conn)
|
||||
conn.on('error', function(err) {
|
||||
log.fatal('InputAgent socket had an error', err.stack)
|
||||
quit.fatal()
|
||||
@@ -137,62 +141,166 @@ module.exports = syrup.serial()
|
||||
return devutil.waitForPortToFree(adb, options.serial, service.port)
|
||||
})
|
||||
.then(function() {
|
||||
return callService(util.format("-a '%s'", service.startAction))
|
||||
return callService(util.format("-a '%s'", apk.startAction))
|
||||
})
|
||||
.then(function() {
|
||||
return devutil.waitForPort(adb, options.serial, service.port)
|
||||
})
|
||||
.then(function(conn) {
|
||||
service.socket = conn
|
||||
service.reader = conn.pipe(new ms.DelimitedStream())
|
||||
service.reader.on('data', function(data) {
|
||||
if (serviceQueue.length) {
|
||||
var resolver = serviceQueue.shift()
|
||||
resolver.resolve(data)
|
||||
}
|
||||
else {
|
||||
log.warn('Unexpected data from service', data)
|
||||
}
|
||||
})
|
||||
service.writer = new ms.DelimitingStream()
|
||||
service.writer.pipe(conn)
|
||||
conn.on('error', function(err) {
|
||||
log.fatal('InputService socket had an error', err.stack)
|
||||
quit.fatal()
|
||||
})
|
||||
conn.on('end', function() {
|
||||
log.fatal('InputService socket ended')
|
||||
quit.fatal()
|
||||
})
|
||||
log.fatal('InputService socket had an error', err.stack)
|
||||
quit.fatal()
|
||||
})
|
||||
.on('end', function() {
|
||||
log.fatal('InputService socket ended')
|
||||
quit.fatal()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function stopService() {
|
||||
return callService(util.format("-a '%s'", service.stopAction))
|
||||
return callService(util.format("-a '%s'", apk.stopAction))
|
||||
}
|
||||
|
||||
function sendInputEvent(event) {
|
||||
var lengthBuffer = new ByteBuffer()
|
||||
, messageBuffer = new apk.proto.InputEvent(event).encode()
|
||||
agent.writer.write(new apk.agentProto.InputEvent(event).encodeNB())
|
||||
}
|
||||
|
||||
// Delimiter
|
||||
lengthBuffer.writeVarint32(messageBuffer.length)
|
||||
|
||||
agent.socket.write(Buffer.concat([
|
||||
lengthBuffer.toBuffer()
|
||||
, messageBuffer.toBuffer()
|
||||
]))
|
||||
function version() {
|
||||
return runServiceCommand(
|
||||
apk.serviceProto.RequestType.VERSION
|
||||
, new apk.serviceProto.VersionRequest()
|
||||
)
|
||||
.then(function(data) {
|
||||
var response = apk.serviceProto.VersionResponse.decode(data)
|
||||
if (response.success) {
|
||||
return response.version
|
||||
}
|
||||
throw new Error('Unable to retrieve version')
|
||||
})
|
||||
}
|
||||
|
||||
function unlock() {
|
||||
service.socket.write('unlock\n')
|
||||
return runServiceCommand(
|
||||
apk.serviceProto.RequestType.SET_KEYGUARD_STATE
|
||||
, new apk.serviceProto.SetKeyguardStateRequest(false)
|
||||
)
|
||||
.then(function(data) {
|
||||
var response = apk.serviceProto.SetKeyguardStateResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to unlock device')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function lock() {
|
||||
service.socket.write('lock\n')
|
||||
return runServiceCommand(
|
||||
apk.serviceProto.RequestType.SET_KEYGUARD_STATE
|
||||
, new apk.serviceProto.SetKeyguardStateRequest(true)
|
||||
)
|
||||
.then(function(data) {
|
||||
var response = apk.serviceProto.SetKeyguardStateResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to lock device')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function acquireWakeLock() {
|
||||
service.socket.write('acquire wake lock\n')
|
||||
return runServiceCommand(
|
||||
apk.serviceProto.RequestType.SET_WAKE_LOCK
|
||||
, new apk.serviceProto.SetWakeLockRequest(true)
|
||||
)
|
||||
.then(function(data) {
|
||||
var response = apk.serviceProto.SetWakeLockResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to acquire WakeLock')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function releaseWakeLock() {
|
||||
service.socket.write('release wake lock\n')
|
||||
return runServiceCommand(
|
||||
apk.serviceProto.RequestType.SET_WAKE_LOCK
|
||||
, new apk.serviceProto.SetWakeLockRequest(false)
|
||||
)
|
||||
.then(function(data) {
|
||||
var response = apk.serviceProto.SetWakeLockResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to release WakeLock')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function identity() {
|
||||
service.socket.write(util.format(
|
||||
'show identity %s\n'
|
||||
, options.serial
|
||||
))
|
||||
return runServiceCommand(
|
||||
apk.serviceProto.RequestType.IDENTIFY
|
||||
, new apk.serviceProto.IdentifyRequest(options.serial)
|
||||
)
|
||||
.then(function(data) {
|
||||
var response = apk.serviceProto.IdentifyResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to identify device')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function setClipboard(text) {
|
||||
return runServiceCommand(
|
||||
apk.serviceProto.RequestType.SET_CLIPBOARD
|
||||
, new apk.serviceProto.SetClipboardRequest(
|
||||
apk.serviceProto.ClipboardType.TEXT
|
||||
, text
|
||||
)
|
||||
)
|
||||
.then(function(data) {
|
||||
var response = apk.serviceProto.SetClipboardResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to set clipboard')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function getClipboard() {
|
||||
return runServiceCommand(
|
||||
apk.serviceProto.RequestType.GET_CLIPBOARD
|
||||
, new apk.serviceProto.GetClipboardRequest(
|
||||
apk.serviceProto.ClipboardType.TEXT
|
||||
)
|
||||
)
|
||||
.then(function(data) {
|
||||
var response = apk.serviceProto.GetClipboardResponse.decode(data)
|
||||
if (response.success) {
|
||||
switch (response.type) {
|
||||
case apk.serviceProto.ClipboardType.TEXT:
|
||||
return response.text
|
||||
}
|
||||
}
|
||||
throw new Error('Unable to get clipboard')
|
||||
})
|
||||
}
|
||||
|
||||
function runServiceCommand(type, cmd) {
|
||||
var resolver = Promise.defer()
|
||||
service.writer.write(new apk.serviceProto.RequestEnvelope(
|
||||
type
|
||||
, cmd.encodeNB()
|
||||
).encodeNB())
|
||||
serviceQueue.push(resolver)
|
||||
return resolver.promise
|
||||
}
|
||||
|
||||
return openAgent()
|
||||
@@ -242,6 +350,17 @@ module.exports = syrup.serial()
|
||||
, acquireWakeLock: acquireWakeLock
|
||||
, releaseWakeLock: releaseWakeLock
|
||||
, identity: identity
|
||||
, paste: function(text) {
|
||||
return setClipboard(text)
|
||||
.then(function() {
|
||||
sendInputEvent({
|
||||
action: 2
|
||||
, keyCode: adb.Keycode.KEYCODE_V
|
||||
, ctrlKey: true
|
||||
})
|
||||
})
|
||||
}
|
||||
, copy: getClipboard
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user