luma_third_party: Logcat Service Rebuild
The previous OpenSTF service implemented an unstable binary connection
to the adb logcat service. This CL rebuilds the service to spawn a
logcat child process for a given device and listen for messages from
stdout.
Change-Id: If32b774bed333b706d6d6ca034b112ccc0988346
diff --git a/crowdstf/lib/units/device/plugins/logcat.js b/crowdstf/lib/units/device/plugins/logcat.js
index c63f208..3645110 100644
--- a/crowdstf/lib/units/device/plugins/logcat.js
+++ b/crowdstf/lib/units/device/plugins/logcat.js
@@ -1,5 +1,6 @@
var syrup = require('stf-syrup')
var Promise = require('bluebird')
+var spawn = require('child_process').spawn;
var logger = require('../../../util/logger')
var wire = require('../../../wire')
@@ -16,70 +17,93 @@
var plugin = Object.create(null)
var activeLogcat = null
+ var openLogcat = function(serial) {
+ return new Promise(function(resolve, reject) {
+ log.info('adb logcat opening stream.');
+
+ // Flag -c clears backlogged output.
+ // Flag -s specifies the device serial.
+ // Option 2>/dev/null ignores process err messages.
+ var psClear = spawn('adb', [
+ '-s',
+ options.serial,
+ 'logcat',
+ '-c',
+ '2>/dev/null'
+ ]);
+
+ psClear.on('close', function(exitCode) {
+ if (exitCode === 0) {
+ // Flag *:D provide info level Debug and higher.
+ // Other flags include
+ // (V)erbose (D)ebug (I)nfo (W)arning (E)rror (F)atal.
+ var logcat = spawn('adb', ['-s',
+ serial,
+ 'logcat',
+ '*:D',
+ '2>/dev/null'
+ ]);
+
+ resolve(logcat);
+ } else {
+ reject();
+ throw Error('Unable to access adb logcat clear process');
+ }
+ });
+ });
+ };
+
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
- })
+ return openLogcat(options.serial);
})
- .timeout(10000)
.then(function(logcat) {
- activeLogcat = logcat
+ activeLogcat = logcat;
function entryListener(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
- ))
- ])
+ try {
+ push.send([
+ group.group,
+ wireutil.envelope(new wire.DeviceLogcatEntryMessage(
+ options.serial,
+ new Date().getTime(),
+ 0,
+ 0,
+ '',
+ '',
+ entry.toString()
+ ))
+ ]);
+ } catch (err) {
+ console.error("Logcat stdout threw", err);
+ }
}
- logcat.on('entry', entryListener)
-
+ logcat.stdout.on('data', entryListener);
return plugin.reset(filters)
- })
- })
- }
+ });
+ });
+ };
plugin.stop = Promise.method(function() {
if (plugin.isRunning()) {
log.info('Stopping logcat')
- activeLogcat.end()
+ activeLogcat.kill();
activeLogcat = null
}
})
plugin.reset = Promise.method(function(filters) {
- if (plugin.isRunning()) {
- activeLogcat
- .resetFilters()
-
- if (filters.length) {
- activeLogcat.excludeAll()
- filters.forEach(function(filter) {
- activeLogcat.include(filter.tag, filter.priority)
- })
- }
- }
- else {
- throw new Error('Logcat is not running')
- }
- })
+ filters = null;
+ });
plugin.isRunning = function() {
- return !!activeLogcat
- }
+ return !!activeLogcat && activeLogcat.kill;
+ };
lifecycle.observe(plugin.stop)
group.on('leave', plugin.stop)