mirror of
https://github.com/openstf/stf
synced 2025-10-05 02:29:26 +02:00
Rename "roles" to "units". Put units in their own folders.
This commit is contained in:
parent
7d9d64ddcb
commit
3a9b193f68
63 changed files with 105 additions and 105 deletions
695
lib/units/device/plugins/service.js
Normal file
695
lib/units/device/plugins/service.js
Normal file
|
@ -0,0 +1,695 @@
|
|||
var util = require('util')
|
||||
var events = require('events')
|
||||
|
||||
var syrup = require('syrup')
|
||||
var Promise = require('bluebird')
|
||||
|
||||
var wire = require('../../../wire')
|
||||
var wireutil = require('../../../wire/util')
|
||||
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')
|
||||
var lifecycle = require('../../../util/lifecycle')
|
||||
|
||||
function MessageResolver() {
|
||||
this.resolvers = Object.create(null)
|
||||
|
||||
this.await = function(id, resolver) {
|
||||
this.resolvers[id] = resolver
|
||||
return resolver.promise
|
||||
}
|
||||
|
||||
this.resolve = function(id, value) {
|
||||
var resolver = this.resolvers[id]
|
||||
delete this.resolvers[id]
|
||||
resolver.resolve(value)
|
||||
return resolver.promise
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = syrup.serial()
|
||||
.dependency(require('../support/adb'))
|
||||
.dependency(require('../support/router'))
|
||||
.dependency(require('../support/push'))
|
||||
.dependency(require('../resources/service'))
|
||||
.define(function(options, adb, router, push, apk) {
|
||||
var log = logger.createLogger('device:plugins:service')
|
||||
var messageResolver = new MessageResolver()
|
||||
var plugin = new events.EventEmitter()
|
||||
|
||||
var agent = {
|
||||
socket: null
|
||||
, writer: null
|
||||
, port: 1090
|
||||
}
|
||||
|
||||
var service = {
|
||||
socket: null
|
||||
, writer: null
|
||||
, reader: null
|
||||
, port: 1100
|
||||
}
|
||||
|
||||
function openAgent() {
|
||||
log.info('Launching agent')
|
||||
return stopAgent()
|
||||
.timeout(15000)
|
||||
.then(function() {
|
||||
return devutil.ensureUnusedPort(adb, options.serial, agent.port)
|
||||
.timeout(10000)
|
||||
})
|
||||
.then(function() {
|
||||
return adb.shell(options.serial, util.format(
|
||||
"export CLASSPATH='%s'; exec app_process /system/bin '%s'"
|
||||
, apk.path
|
||||
, apk.main
|
||||
))
|
||||
.timeout(10000)
|
||||
})
|
||||
.then(function(out) {
|
||||
lifecycle.share('Agent shell', out)
|
||||
streamutil.talk(log, 'Agent says: "%s"', out)
|
||||
})
|
||||
.then(function() {
|
||||
return devutil.waitForPort(adb, options.serial, agent.port)
|
||||
.timeout(10000)
|
||||
})
|
||||
.then(function(conn) {
|
||||
agent.socket = conn
|
||||
agent.writer = new ms.DelimitingStream()
|
||||
agent.writer.pipe(conn)
|
||||
lifecycle.share('Agent connection', conn)
|
||||
})
|
||||
}
|
||||
|
||||
function stopAgent() {
|
||||
return devutil.killProcsByComm(
|
||||
adb
|
||||
, options.serial
|
||||
, 'stf.agent'
|
||||
, 'stf.agent'
|
||||
)
|
||||
}
|
||||
|
||||
function callService(intent) {
|
||||
return adb.shell(options.serial, util.format(
|
||||
'am startservice --user 0 %s'
|
||||
, intent
|
||||
))
|
||||
.timeout(15000)
|
||||
.then(function(out) {
|
||||
return streamutil.findLine(out, /^Error/)
|
||||
.finally(function() {
|
||||
out.end()
|
||||
})
|
||||
.timeout(10000)
|
||||
.then(function(line) {
|
||||
if (line.indexOf('--user') !== -1) {
|
||||
return adb.shell(options.serial, util.format(
|
||||
'am startservice %s'
|
||||
, intent
|
||||
))
|
||||
.timeout(15000)
|
||||
.then(function() {
|
||||
return streamutil.findLine(out, /^Error/)
|
||||
.finally(function() {
|
||||
out.end()
|
||||
})
|
||||
.timeout(10000)
|
||||
.then(function(line) {
|
||||
throw new Error(util.format(
|
||||
'Service had an error: "%s"'
|
||||
, line
|
||||
))
|
||||
})
|
||||
.catch(streamutil.NoSuchLineError, function() {
|
||||
return true
|
||||
})
|
||||
})
|
||||
}
|
||||
else {
|
||||
throw new Error(util.format(
|
||||
'Service had an error: "%s"'
|
||||
, line
|
||||
))
|
||||
}
|
||||
})
|
||||
.catch(streamutil.NoSuchLineError, function() {
|
||||
return true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// The APK should be up to date at this point. If it was reinstalled, the
|
||||
// service should have been automatically stopped while it was happening.
|
||||
// So, we should be good to go.
|
||||
function openService() {
|
||||
log.info('Launching service')
|
||||
return callService(util.format(
|
||||
"-a '%s' -n '%s'"
|
||||
, apk.startIntent.action
|
||||
, apk.startIntent.component
|
||||
))
|
||||
.then(function() {
|
||||
return devutil.waitForPort(adb, options.serial, service.port)
|
||||
.timeout(15000)
|
||||
})
|
||||
.then(function(conn) {
|
||||
service.socket = conn
|
||||
service.reader = conn.pipe(new ms.DelimitedStream())
|
||||
service.reader.on('data', handleEnvelope)
|
||||
service.writer = new ms.DelimitingStream()
|
||||
service.writer.pipe(conn)
|
||||
lifecycle.share('Service connection', conn)
|
||||
})
|
||||
}
|
||||
|
||||
function handleEnvelope(data) {
|
||||
var envelope = apk.wire.Envelope.decode(data)
|
||||
, message
|
||||
if (envelope.id !== null) {
|
||||
messageResolver.resolve(envelope.id, envelope.message)
|
||||
}
|
||||
else {
|
||||
switch (envelope.type) {
|
||||
case apk.wire.MessageType.EVENT_AIRPLANE_MODE:
|
||||
message = apk.wire.AirplaneModeEvent.decode(envelope.message)
|
||||
push.send([
|
||||
wireutil.global
|
||||
, wireutil.envelope(new wire.AirplaneModeEvent(
|
||||
options.serial
|
||||
, message.enabled
|
||||
))
|
||||
])
|
||||
plugin.emit('airplaneModeChange', message)
|
||||
break
|
||||
case apk.wire.MessageType.EVENT_BATTERY:
|
||||
message = apk.wire.BatteryEvent.decode(envelope.message)
|
||||
push.send([
|
||||
wireutil.global
|
||||
, wireutil.envelope(new wire.BatteryEvent(
|
||||
options.serial
|
||||
, message.status
|
||||
, message.health
|
||||
, message.source
|
||||
, message.level
|
||||
, message.scale
|
||||
, message.temp
|
||||
, message.voltage
|
||||
))
|
||||
])
|
||||
plugin.emit('batteryChange', message)
|
||||
break
|
||||
case apk.wire.MessageType.EVENT_BROWSER_PACKAGE:
|
||||
message = apk.wire.BrowserPackageEvent.decode(envelope.message)
|
||||
plugin.emit('browserPackageChange', message)
|
||||
break
|
||||
case apk.wire.MessageType.EVENT_CONNECTIVITY:
|
||||
message = apk.wire.ConnectivityEvent.decode(envelope.message)
|
||||
push.send([
|
||||
wireutil.global
|
||||
, wireutil.envelope(new wire.ConnectivityEvent(
|
||||
options.serial
|
||||
, message.connected
|
||||
, message.type
|
||||
, message.subtype
|
||||
, message.failover
|
||||
, message.roaming
|
||||
))
|
||||
])
|
||||
plugin.emit('connectivityChange', message)
|
||||
break
|
||||
case apk.wire.MessageType.EVENT_PHONE_STATE:
|
||||
message = apk.wire.PhoneStateEvent.decode(envelope.message)
|
||||
push.send([
|
||||
wireutil.global
|
||||
, wireutil.envelope(new wire.PhoneStateEvent(
|
||||
options.serial
|
||||
, message.state
|
||||
, message.manual
|
||||
, message.operator
|
||||
))
|
||||
])
|
||||
plugin.emit('phoneStateChange', message)
|
||||
break
|
||||
case apk.wire.MessageType.EVENT_ROTATION:
|
||||
message = apk.wire.RotationEvent.decode(envelope.message)
|
||||
push.send([
|
||||
wireutil.global
|
||||
, wireutil.envelope(new wire.RotationEvent(
|
||||
options.serial
|
||||
, message.rotation
|
||||
))
|
||||
])
|
||||
plugin.emit('rotationChange', message)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function keyEvent(data) {
|
||||
return runAgentCommand(
|
||||
apk.wire.MessageType.DO_KEYEVENT
|
||||
, new apk.wire.KeyEventRequest(data)
|
||||
)
|
||||
}
|
||||
|
||||
plugin.type = function(text) {
|
||||
return runAgentCommand(
|
||||
apk.wire.MessageType.DO_TYPE
|
||||
, new apk.wire.DoTypeRequest(text)
|
||||
)
|
||||
}
|
||||
|
||||
plugin.paste = function(text) {
|
||||
return plugin.setClipboard(text)
|
||||
.then(function() {
|
||||
keyEvent({
|
||||
event: apk.wire.KeyEvent.PRESS
|
||||
, keyCode: adb.Keycode.KEYCODE_V
|
||||
, ctrlKey: true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
plugin.copy = function() {
|
||||
// @TODO Not sure how to force the device to copy the current selection
|
||||
// yet.
|
||||
return plugin.getClipboard()
|
||||
}
|
||||
|
||||
plugin.getDisplay = function(id) {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.GET_DISPLAY
|
||||
, new apk.wire.GetDisplayRequest(id)
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.GetDisplayResponse.decode(data)
|
||||
if (response.success) {
|
||||
return {
|
||||
id: id
|
||||
, width: response.width
|
||||
, height: response.height
|
||||
, xdpi: response.xdpi
|
||||
, ydpi: response.ydpi
|
||||
, fps: response.fps
|
||||
, density: response.density
|
||||
, rotation: response.rotation
|
||||
, secure: response.secure
|
||||
}
|
||||
}
|
||||
throw new Error('Unable to retrieve display information')
|
||||
})
|
||||
}
|
||||
|
||||
plugin.wake = function() {
|
||||
return runAgentCommand(
|
||||
apk.wire.MessageType.DO_WAKE
|
||||
, new apk.wire.DoWakeRequest()
|
||||
)
|
||||
}
|
||||
|
||||
plugin.rotate = function(rotation) {
|
||||
return runAgentCommand(
|
||||
apk.wire.MessageType.SET_ROTATION
|
||||
, new apk.wire.SetRotationRequest(rotation, false)
|
||||
)
|
||||
}
|
||||
|
||||
plugin.freezeRotation = function(rotation) {
|
||||
return runAgentCommand(
|
||||
apk.wire.MessageType.SET_ROTATION
|
||||
, new apk.wire.SetRotationRequest(rotation, true)
|
||||
)
|
||||
}
|
||||
|
||||
plugin.thawRotation = function() {
|
||||
return runAgentCommand(
|
||||
apk.wire.MessageType.SET_ROTATION
|
||||
, new apk.wire.SetRotationRequest(0, false)
|
||||
)
|
||||
}
|
||||
|
||||
plugin.version = function() {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.GET_VERSION
|
||||
, new apk.wire.GetVersionRequest()
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.GetVersionResponse.decode(data)
|
||||
if (response.success) {
|
||||
return response.version
|
||||
}
|
||||
throw new Error('Unable to retrieve version')
|
||||
})
|
||||
}
|
||||
|
||||
plugin.unlock = function() {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.SET_KEYGUARD_STATE
|
||||
, new apk.wire.SetKeyguardStateRequest(false)
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.SetKeyguardStateResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to unlock device')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
plugin.lock = function() {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.SET_KEYGUARD_STATE
|
||||
, new apk.wire.SetKeyguardStateRequest(true)
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.SetKeyguardStateResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to lock device')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
plugin.acquireWakeLock = function() {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.SET_WAKE_LOCK
|
||||
, new apk.wire.SetWakeLockRequest(true)
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.SetWakeLockResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to acquire WakeLock')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
plugin.releaseWakeLock = function() {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.SET_WAKE_LOCK
|
||||
, new apk.wire.SetWakeLockRequest(false)
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.SetWakeLockResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to release WakeLock')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
plugin.identity = function() {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.DO_IDENTIFY
|
||||
, new apk.wire.DoIdentifyRequest(options.serial)
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.DoIdentifyResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to identify device')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
plugin.setClipboard = function(text) {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.SET_CLIPBOARD
|
||||
, new apk.wire.SetClipboardRequest(
|
||||
apk.wire.ClipboardType.TEXT
|
||||
, text
|
||||
)
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.SetClipboardResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to set clipboard')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
plugin.getClipboard = function() {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.GET_CLIPBOARD
|
||||
, new apk.wire.GetClipboardRequest(
|
||||
apk.wire.ClipboardType.TEXT
|
||||
)
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.GetClipboardResponse.decode(data)
|
||||
if (response.success) {
|
||||
switch (response.type) {
|
||||
case apk.wire.ClipboardType.TEXT:
|
||||
return response.text
|
||||
}
|
||||
}
|
||||
throw new Error('Unable to get clipboard')
|
||||
})
|
||||
}
|
||||
|
||||
plugin.getBrowsers = function() {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.GET_BROWSERS
|
||||
, new apk.wire.GetBrowsersRequest()
|
||||
)
|
||||
.timeout(15000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.GetBrowsersResponse.decode(data)
|
||||
if (response.success) {
|
||||
delete response.success
|
||||
return response
|
||||
}
|
||||
throw new Error('Unable to get browser list')
|
||||
})
|
||||
}
|
||||
|
||||
plugin.getProperties = function(properties) {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.GET_PROPERTIES
|
||||
, new apk.wire.GetPropertiesRequest(properties)
|
||||
)
|
||||
.timeout(15000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.GetPropertiesResponse.decode(data)
|
||||
if (response.success) {
|
||||
var mapped = Object.create(null)
|
||||
response.properties.forEach(function(property) {
|
||||
mapped[property.name] = property.value
|
||||
})
|
||||
return mapped
|
||||
}
|
||||
throw new Error('Unable to get properties')
|
||||
})
|
||||
}
|
||||
|
||||
plugin.getAccounts = function(data) {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.GET_ACCOUNTS
|
||||
, new apk.wire.GetAccountsRequest({type: data.type})
|
||||
)
|
||||
.timeout(15000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.GetAccountsResponse.decode(data)
|
||||
if (response.success) {
|
||||
return response.accounts
|
||||
}
|
||||
throw new Error('No accounts returned')
|
||||
})
|
||||
}
|
||||
|
||||
plugin.removeAccount = function(data) {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.DO_REMOVE_ACCOUNT
|
||||
, new apk.wire.DoRemoveAccountRequest({
|
||||
type: data.type
|
||||
, account: data.account
|
||||
})
|
||||
)
|
||||
.timeout(15000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.DoRemoveAccountResponse.decode(data)
|
||||
if (response.success) {
|
||||
return true
|
||||
}
|
||||
throw new Error('Unable to remove account')
|
||||
})
|
||||
}
|
||||
|
||||
plugin.addAccountMenu = function() {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.DO_ADD_ACCOUNT_MENU
|
||||
, new apk.wire.DoAddAccountMenuRequest()
|
||||
)
|
||||
.timeout(15000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.DoAddAccountMenuResponse.decode(data)
|
||||
if (response.success) {
|
||||
return true
|
||||
}
|
||||
throw new Error('Unable to show add account menu')
|
||||
})
|
||||
}
|
||||
|
||||
plugin.setRingerMode = function(mode) {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.SET_RINGER_MODE
|
||||
, new apk.wire.SetRingerModeRequest(mode)
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.SetRingerModeResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to set ringer mode')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
plugin.getRingerMode = function() {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.GET_RINGER_MODE
|
||||
, new apk.wire.GetRingerModeRequest()
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.GetRingerModeResponse.decode(data)
|
||||
// Reflection to decode enums to their string values, otherwise
|
||||
// we only get an integer
|
||||
var ringerMode = apk.builder.lookup('jp.co.cyberagent.stf.proto.RingerMode')
|
||||
.children[response.mode].name
|
||||
if (response.success) {
|
||||
return ringerMode
|
||||
}
|
||||
throw new Error('Unable to get ringer mode')
|
||||
})
|
||||
}
|
||||
|
||||
plugin.setWifiEnabled = function(enabled) {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.SET_WIFI_ENABLED
|
||||
, new apk.wire.SetWifiEnabledRequest(enabled)
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.SetWifiEnabledResponse.decode(data)
|
||||
if (!response.success) {
|
||||
throw new Error('Unable to set Wifi')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
plugin.getWifiStatus = function() {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.GET_WIFI_STATUS
|
||||
, new apk.wire.GetWifiStatusRequest()
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.GetWifiStatusResponse.decode(data)
|
||||
if (response.success) {
|
||||
return response.status
|
||||
}
|
||||
throw new Error('Unable to get Wifi status')
|
||||
})
|
||||
}
|
||||
|
||||
plugin.getSdStatus = function () {
|
||||
return runServiceCommand(
|
||||
apk.wire.MessageType.GET_SD_STATUS
|
||||
, new apk.wire.GetSdStatusRequest()
|
||||
)
|
||||
.timeout(10000)
|
||||
.then(function(data) {
|
||||
var response = apk.wire.GetSdStatusResponse.decode(data)
|
||||
if (response.success) {
|
||||
return response.mounted
|
||||
}
|
||||
throw new Error('Unable to get SD card status')
|
||||
})
|
||||
}
|
||||
|
||||
plugin.pressKey = function(key) {
|
||||
keyEvent({event: apk.wire.KeyEvent.PRESS, keyCode: keyutil.namedKey(key)})
|
||||
return Promise.resolve(true)
|
||||
}
|
||||
|
||||
function runServiceCommand(type, cmd) {
|
||||
var resolver = Promise.defer()
|
||||
var id = Math.floor(Math.random() * 0xFFFFFF)
|
||||
service.writer.write(new apk.wire.Envelope(
|
||||
id
|
||||
, type
|
||||
, cmd.encodeNB()
|
||||
).encodeNB())
|
||||
return messageResolver.await(id, resolver)
|
||||
}
|
||||
|
||||
function runAgentCommand(type, cmd) {
|
||||
agent.writer.write(new apk.wire.Envelope(
|
||||
null
|
||||
, type
|
||||
, cmd.encodeNB()
|
||||
).encodeNB())
|
||||
}
|
||||
|
||||
return openAgent()
|
||||
.then(openService)
|
||||
.then(function() {
|
||||
router
|
||||
.on(wire.PhysicalIdentifyMessage, function(channel) {
|
||||
var reply = wireutil.reply(options.serial)
|
||||
plugin.identity()
|
||||
push.send([
|
||||
channel
|
||||
, reply.okay()
|
||||
])
|
||||
})
|
||||
.on(wire.KeyDownMessage, function(channel, message) {
|
||||
try {
|
||||
keyEvent({
|
||||
event: apk.wire.KeyEvent.DOWN
|
||||
, keyCode: keyutil.namedKey(message.key)
|
||||
})
|
||||
}
|
||||
catch(e) {
|
||||
log.warn(e.message)
|
||||
}
|
||||
})
|
||||
.on(wire.KeyUpMessage, function(channel, message) {
|
||||
try {
|
||||
keyEvent({
|
||||
event: apk.wire.KeyEvent.UP
|
||||
, keyCode: keyutil.namedKey(message.key)
|
||||
})
|
||||
}
|
||||
catch(e) {
|
||||
log.warn(e.message)
|
||||
}
|
||||
})
|
||||
.on(wire.KeyPressMessage, function(channel, message) {
|
||||
try {
|
||||
keyEvent({
|
||||
event: apk.wire.KeyEvent.PRESS
|
||||
, keyCode: keyutil.namedKey(message.key)
|
||||
})
|
||||
}
|
||||
catch(e) {
|
||||
log.warn(e.message)
|
||||
}
|
||||
})
|
||||
.on(wire.TypeMessage, function(channel, message) {
|
||||
plugin.type(message.text)
|
||||
})
|
||||
.on(wire.RotateMessage, function(channel, message) {
|
||||
plugin.rotate(message.rotation)
|
||||
})
|
||||
})
|
||||
.return(plugin)
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue