From 8da5b61289a18312afbdc9f21af30d7c0d8a3abd Mon Sep 17 00:00:00 2001 From: Simo Kinnunen Date: Thu, 17 Apr 2014 18:27:35 +0900 Subject: [PATCH] Logcat works now, but still kind of wondering how the messages should arrive. --- lib/roles/app.js | 23 +++ lib/roles/device/plugins/group.js | 137 ++++++++-------- lib/roles/device/plugins/logcat.js | 155 +++++++++++++----- lib/roles/processor.js | 3 + lib/util/grouputil.js | 10 +- lib/wire/wire.proto | 9 + .../components/stf/control/control-service.js | 10 ++ 7 files changed, 240 insertions(+), 107 deletions(-) diff --git a/lib/roles/app.js b/lib/roles/app.js index 01a68246..1010e07c 100644 --- a/lib/roles/app.js +++ b/lib/roles/app.js @@ -324,6 +324,9 @@ module.exports = function(options) { .on(wire.TransactionDoneMessage, function(channel, message) { socket.emit('tx.done', channel.toString(), message) }) + .on(wire.DeviceLogcatEntryMessage, function(channel, message) { + socket.emit('logcat.entry', message) + }) .handler() // Global messages @@ -530,6 +533,26 @@ module.exports = function(options) { ]) }) }) + .on('logcat.start', function(channel, responseChannel, data) { + joinChannel(responseChannel) + push.send([ + channel + , wireutil.transaction( + responseChannel + , new wire.LogcatStartMessage(data) + ) + ]) + }) + .on('logcat.stop', function(channel, responseChannel) { + joinChannel(responseChannel) + push.send([ + channel + , wireutil.transaction( + responseChannel + , new wire.LogcatStopMessage() + ) + ]) + }) }) .finally(function() { // Clean up all listeners and subscriptions diff --git a/lib/roles/device/plugins/group.js b/lib/roles/device/plugins/group.js index 453d64e5..783fd5c2 100644 --- a/lib/roles/device/plugins/group.js +++ b/lib/roles/device/plugins/group.js @@ -19,71 +19,76 @@ module.exports = syrup.serial() .define(function(options, identity, input, router, push, sub, channels) { var log = logger.createLogger('device:plugins:group') , currentGroup = null - , emitter = new events.EventEmitter() + , plugin = new events.EventEmitter() - function joinGroup(newGroup, timeout) { - if (currentGroup) { - return Promise.reject(new grouputil.AlreadyGroupedError()) + plugin.get = Promise.method(function() { + if (!currentGroup) { + throw new grouputil.NoGroupError() } - currentGroup = newGroup + return currentGroup + }) - log.info('Now owned by "%s"', currentGroup.email) - log.info('Subscribing to group channel "%s"', currentGroup.group) + plugin.join = function(newGroup, timeout) { + return plugin.get() + .then(function() { + throw new grouputil.AlreadyGroupedError() + }) + .catch(grouputil.NoGroupError, function() { + currentGroup = newGroup - channels.register(currentGroup.group, timeout) - sub.subscribe(currentGroup.group) + log.info('Now owned by "%s"', currentGroup.email) + log.info('Subscribing to group channel "%s"', currentGroup.group) - push.send([ - wireutil.global - , wireutil.envelope(new wire.JoinGroupMessage( - options.serial - , currentGroup - )) - ]) + channels.register(currentGroup.group, timeout) + sub.subscribe(currentGroup.group) + push.send([ + wireutil.global + , wireutil.envelope(new wire.JoinGroupMessage( + options.serial + , currentGroup + )) + ]) + + plugin.emit('join', currentGroup) + + return currentGroup + }) + } + + plugin.leave = function() { + return plugin.get() + .then(function(group) { + log.info('No longer owned by "%s"', group.email) + log.info('Unsubscribing from group channel "%s"', group.group) + + channels.unregister(group.group) + sub.unsubscribe(group.group) + + push.send([ + wireutil.global + , wireutil.envelope(new wire.LeaveGroupMessage( + options.serial + , group + )) + ]) + + currentGroup = null + plugin.emit('leave', group) + + return group + }) + } + + plugin.on('join', function() { input.acquireWakeLock() input.unlock() + }) - emitter.emit('join', currentGroup) - - return Promise.resolve(currentGroup) - } - - function leaveGroup() { - if (!currentGroup) { - return Promise.reject(new grouputil.NotGroupedError()) - } - - log.info('No longer owned by "%s"', currentGroup.email) - log.info('Unsubscribing from group channel "%s"', currentGroup.group) - - channels.unregister(currentGroup.group) - sub.unsubscribe(currentGroup.group) - - push.send([ - wireutil.global - , wireutil.envelope(new wire.LeaveGroupMessage( - options.serial - , currentGroup - )) - ]) - + plugin.on('leave', function() { input.releaseWakeLock() input.lock() - - var oldGroup = currentGroup - currentGroup = null - - emitter.emit('leave', oldGroup) - - return Promise.resolve(oldGroup) - } - - channels.on('timeout', function(channel) { - if (currentGroup && channel === currentGroup.group) { - leaveGroup() - } }) router @@ -91,7 +96,7 @@ module.exports = syrup.serial() var reply = wireutil.reply(options.serial) grouputil.match(identity, message.requirements) .then(function() { - return joinGroup(message.owner) + return plugin.join(message.owner, message.timeout) }) .then(function() { push.send([ @@ -116,7 +121,7 @@ module.exports = syrup.serial() var reply = wireutil.reply(options.serial) grouputil.match(identity, message.requirements) .then(function() { - return leaveGroup() + return plugin.leave() }) .then(function() { push.send([ @@ -124,7 +129,7 @@ module.exports = syrup.serial() , reply.okay() ]) }) - .catch(grouputil.NotGroupedError, function(err) { + .catch(grouputil.NoGroupError, function(err) { push.send([ channel , reply.fail(err.message) @@ -132,15 +137,19 @@ module.exports = syrup.serial() }) }) - lifecycle.observe(function() { - if (currentGroup) { - leaveGroup() - return Promise.delay(500) - } - else { - return true + channels.on('timeout', function(channel) { + if (currentGroup && channel === currentGroup.group) { + plugin.leave() } }) - return emitter + lifecycle.observe(function() { + return plugin.leave() + .delay(500) // Make sure that the message gets sent + .catch(grouputil.NoGroupError, function() { + return true + }) + }) + + return plugin }) diff --git a/lib/roles/device/plugins/logcat.js b/lib/roles/device/plugins/logcat.js index 3c190c41..da055754 100644 --- a/lib/roles/device/plugins/logcat.js +++ b/lib/roles/device/plugins/logcat.js @@ -1,4 +1,5 @@ var syrup = require('syrup') +var Promise = require('bluebird') var logger = require('../../../util/logger') var wire = require('../../../wire') @@ -10,52 +11,130 @@ module.exports = syrup.serial() .dependency(require('../support/router')) .dependency(require('../support/push')) .dependency(require('./group')) - .define(function(options, adb, router, push, owner) { + .define(function(options, adb, router, push, group) { var log = logger.createLogger('device:plugins:logcat') + , plugin = Object.create(null) + , activeLogcat = null - function openService() { - log.info('Launching logcat service') - return adb.openLogcat(options.serial) - .timeout(10000) - .then(function(logcat) { - return lifecycle.share('Logcat', logcat) + plugin.start = function(filters) { + return group.get() + .then(function(group) { + return plugin.stop() + .then(function() { + log.info('Starting logcat') + return adb.openLogcat(options.serial, { + clear: true + }) + }) + .timeout(10000) + .then(function(logcat) { + activeLogcat = logcat + + function entryListener(entry) { + console.log('sending', entry) + push.send([ + group.group + , wireutil.envelope(new wire.DeviceLogcatEntryMessage( + options.serial + , entry.date.getTime() / 1000 + , entry.pid + , entry.tid + , entry.priority + , entry.tag + , entry.message + )) + ]) + } + + logcat.on('entry', entryListener) + + return plugin.reset(filters) + }) }) } - return openService() - .then(function(logcat) { - function reset() { - logcat - .resetFilters() - .excludeAll() - } + plugin.stop = Promise.method(function() { + if (plugin.isRunning()) { + log.info('Stopping logcat') + activeLogcat.end() + activeLogcat = null + } + }) - function entryListener(entry) { - push.send([ - owner.group - , wireutil.envelope(new wire.DeviceLogcatEntryMessage( - options.serial - , entry.date.getTime() / 1000 - , entry.pid - , entry.tid - , entry.priority - , entry.tag - , entry.message - )) - ]) - } + plugin.reset = Promise.method(function(filters) { + if (plugin.isRunning()) { + activeLogcat + .resetFilters() + .excludeAll() - reset() - logcat.on('entry', entryListener) + filters.forEach(function(filter) { + activeLogcat.include(filter.tag, filter.priority) + }) + } + else { + throw new Error('Logcat is not running') + } + }) - router - .on(wire.LogcatApplyFiltersMessage, function(channel, message) { - reset() - message.filters.forEach(function(filter) { - logcat.include(filter.tag, filter.priority) - }) + plugin.isRunning = function() { + return !!activeLogcat + } + + lifecycle.observe(plugin.stop) + group.on('leave', plugin.stop) + + router + .on(wire.LogcatStartMessage, function(channel, message) { + var reply = wireutil.reply(options.serial) + plugin.start(message.filters) + .then(function() { + push.send([ + channel + , reply.okay('success') + ]) + }) + .catch(function(err) { + log.error('Unable to open logcat', err.stack) + push.send([ + channel + , reply.fail('fail') + ]) }) - - return logcat }) + .on(wire.LogcatApplyFiltersMessage, function(channel, message) { + var reply = wireutil.reply(options.serial) + plugin.reset(message.filters) + .then(function() { + push.send([ + channel + , reply.okay('success') + ]) + }) + .catch(function(err) { + log.error('Failed to apply logcat filters', err.stack) + push.send([ + channel + , reply.fail('fail') + ]) + }) + }) + .on(wire.LogcatStopMessage, function(channel) { + var reply = wireutil.reply(options.serial) + plugin.stop() + .then(function() { + push.send([ + channel + , reply.okay('success') + ]) + }) + .catch(function(err) { + log.error('Failed to stop logcat', err.stack) + push.send([ + channel + , reply.fail('fail') + ]) + }) + }) + + return plugin }) diff --git a/lib/roles/processor.js b/lib/roles/processor.js index eaabb607..076021f9 100644 --- a/lib/roles/processor.js +++ b/lib/roles/processor.js @@ -91,6 +91,9 @@ module.exports = function(options) { .on(wire.TransactionDoneMessage, function(channel, message, data) { appDealer.send([channel, data]) }) + .on(wire.DeviceLogcatEntryMessage, function(channel, message, data) { + appDealer.send([channel, data]) + }) .handler()) lifecycle.observe(function() { diff --git a/lib/util/grouputil.js b/lib/util/grouputil.js index 5ed40623..31b6be9d 100644 --- a/lib/util/grouputil.js +++ b/lib/util/grouputil.js @@ -28,16 +28,16 @@ util.inherits(AlreadyGroupedError, Error) module.exports.AlreadyGroupedError = AlreadyGroupedError -function NotGroupedError() { +function NoGroupError() { Error.call(this) - this.name = 'NotGroupedError' + this.name = 'NoGroupError' this.message = 'Not a member of any group' - Error.captureStackTrace(this, NotGroupedError) + Error.captureStackTrace(this, NoGroupError) } -util.inherits(NotGroupedError, Error) +util.inherits(NoGroupError, Error) -module.exports.NotGroupedError = NotGroupedError +module.exports.NoGroupError = NoGroupError module.exports.match = Promise.method(function(capabilities, requirements) { return requirements.every(function(req) { diff --git a/lib/wire/wire.proto b/lib/wire/wire.proto index a9228754..8cd1c2e1 100644 --- a/lib/wire/wire.proto +++ b/lib/wire/wire.proto @@ -39,6 +39,8 @@ enum MessageType { ForwardTestMessage = 36; ForwardCreateMessage = 37; ForwardRemoveMessage = 38; + LogcatStartMessage = 39; + LogcatStopMessage = 40; } message Envelope { @@ -316,6 +318,13 @@ message LogcatFilter { required uint32 priority = 2; } +message LogcatStartMessage { + repeated LogcatFilter filters = 1; +} + +message LogcatStopMessage { +} + message LogcatApplyFiltersMessage { repeated LogcatFilter filters = 1; } diff --git a/res/app/components/stf/control/control-service.js b/res/app/components/stf/control/control-service.js index d934f79b..c0374d6d 100644 --- a/res/app/components/stf/control/control-service.js +++ b/res/app/components/stf/control/control-service.js @@ -187,6 +187,16 @@ module.exports = function ControlServiceFactory( devicePort: forward.devicePort }) } + + this.startLogcat = function(filters) { + return sendTwoWay('logcat.start', { + filters: filters + }) + } + + this.stopLogcat = function() { + return sendTwoWay('logcat.stop') + } } controlService.create = function(target, channel) {