Bug 1101994 - Add a low-pass filter to LogShake's shake detection and refactor unit tests to be less redundant. r=mhenretty, r=gerard-majax

This commit is contained in:
James Hobin 2015-06-10 17:22:00 -04:00
Родитель 3122e1ac66
Коммит 0527511de5
2 изменённых файлов: 98 добавлений и 47 удалений

Просмотреть файл

@ -51,9 +51,15 @@ function debug(msg) {
/**
* An empirically determined amount of acceleration corresponding to a
* shake
* shake.
*/
const EXCITEMENT_THRESHOLD = 500;
/**
* The maximum fraction to update the excitement value per frame. This
* corresponds to requiring shaking for approximately 10 motion events (1.6
* seconds)
*/
const EXCITEMENT_FILTER_ALPHA = 0.2;
const DEVICE_MOTION_EVENT = "devicemotion";
const SCREEN_CHANGE_EVENT = "screenchange";
const CAPTURE_LOGS_CONTENT_EVENT = "requestSystemLogs";
@ -88,6 +94,11 @@ let LogShake = {
*/
captureRequested: false,
/**
* The current excitement (movement) level
*/
excitement: 0,
/**
* Map of files which have log-type information to their parsers
*/
@ -122,6 +133,9 @@ let LogShake = {
screenEnabled: true
}});
// Reset excitement to clear residual motion
this.excitement = 0;
SystemAppProxy.addEventListener(CAPTURE_LOGS_CONTENT_EVENT, this, false);
SystemAppProxy.addEventListener(SCREEN_CHANGE_EVENT, this, false);
@ -196,9 +210,12 @@ let LogShake = {
var acc = event.accelerationIncludingGravity;
var excitement = acc.x * acc.x + acc.y * acc.y + acc.z * acc.z;
// Updates excitement by a factor of at most alpha, ignoring sudden device
// motion. See bug #1101994 for more information.
var newExcitement = acc.x * acc.x + acc.y * acc.y + acc.z * acc.z;
this.excitement += (newExcitement - this.excitement) * EXCITEMENT_FILTER_ALPHA;
if (excitement > EXCITEMENT_THRESHOLD) {
if (this.excitement > EXCITEMENT_THRESHOLD) {
this.startCapture();
}
},

Просмотреть файл

@ -15,9 +15,14 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/LogCapture.jsm");
Cu.import("resource://gre/modules/LogShake.jsm");
// Force logshake to handle a device motion event with given components
// Does not use SystemAppProxy because event needs special
// accelerationIncludingGravity property
const EVENTS_PER_SECOND = 6.25;
const GRAVITY = 9.8;
/**
* Force logshake to handle a device motion event with given components.
* Does not use SystemAppProxy because event needs special
* accelerationIncludingGravity property.
*/
function sendDeviceMotionEvent(x, y, z) {
let event = {
type: "devicemotion",
@ -30,8 +35,10 @@ function sendDeviceMotionEvent(x, y, z) {
LogShake.handleEvent(event);
}
// Send a screen change event directly, does not use SystemAppProxy due to race
// conditions.
/**
* Send a screen change event directly, does not use SystemAppProxy due to race
* conditions.
*/
function sendScreenChangeEvent(screenEnabled) {
let event = {
type: "screenchange",
@ -42,23 +49,41 @@ function sendScreenChangeEvent(screenEnabled) {
LogShake.handleEvent(event);
}
function debug(msg) {
var timestamp = Date.now();
dump("LogShake: " + timestamp + ": " + msg);
/**
* Mock the readLogFile function of LogCapture.
* Used to detect whether LogShake activates.
* @return {Array<String>} Locations that LogShake tries to read
*/
function mockReadLogFile() {
let readLocations = [];
LogCapture.readLogFile = function(loc) {
readLocations.push(loc);
return null; // we don't want to provide invalid data to a parser
};
// Allow inspection of readLocations by caller
return readLocations;
}
/**
* Send a series of events that corresponds to a shake
*/
function sendSustainedShake() {
// Fire a series of devicemotion events that are of shake magnitude
for (let i = 0; i < 2 * EVENTS_PER_SECOND; i++) {
sendDeviceMotionEvent(0, 2 * GRAVITY, 2 * GRAVITY);
}
}
add_test(function test_do_log_capture_after_shaking() {
// Enable LogShake
LogShake.init();
let readLocations = [];
LogCapture.readLogFile = function(loc) {
readLocations.push(loc);
return null; // we don't want to provide invalid data to a parser
};
let readLocations = mockReadLogFile();
// Fire a devicemotion event that is of shake magnitude
sendDeviceMotionEvent(9001, 9001, 9001);
sendSustainedShake();
ok(readLocations.length > 0,
"LogShake should attempt to read at least one log");
@ -71,36 +96,28 @@ add_test(function test_do_nothing_when_resting() {
// Enable LogShake
LogShake.init();
let readLocations = [];
LogCapture.readLogFile = function(loc) {
readLocations.push(loc);
return null; // we don't want to provide invalid data to a parser
};
let readLocations = mockReadLogFile();
// Fire a devicemotion event that is relatively tiny
sendDeviceMotionEvent(0, 9.8, 9.8);
// Fire several devicemotion events that are relatively tiny
for (let i = 0; i < 2 * EVENTS_PER_SECOND; i++) {
sendDeviceMotionEvent(0, GRAVITY, GRAVITY);
}
ok(readLocations.length === 0,
"LogShake should not read any logs");
debug("test_do_nothing_when_resting: stop");
LogShake.uninit();
run_next_test();
});
add_test(function test_do_nothing_when_disabled() {
debug("test_do_nothing_when_disabled: start");
// Disable LogShake
LogShake.uninit();
let readLocations = [];
LogCapture.readLogFile = function(loc) {
readLocations.push(loc);
return null; // we don't want to provide invalid data to a parser
};
let readLocations = mockReadLogFile();
// Fire a devicemotion event that would normally be a shake
sendDeviceMotionEvent(0, 9001, 9001);
// Fire a series of events that would normally be a shake
sendSustainedShake();
ok(readLocations.length === 0,
"LogShake should not read any logs");
@ -112,18 +129,13 @@ add_test(function test_do_nothing_when_screen_off() {
// Enable LogShake
LogShake.init();
// Send an event as if the screen has been turned off
sendScreenChangeEvent(false);
let readLocations = [];
LogCapture.readLogFile = function(loc) {
readLocations.push(loc);
return null; // we don't want to provide invalid data to a parser
};
let readLocations = mockReadLogFile();
// Fire a devicemotion event that would normally be a shake
sendDeviceMotionEvent(0, 9001, 9001);
// Fire a series of events that would normally be a shake
sendSustainedShake();
ok(readLocations.length === 0,
"LogShake should not read any logs");
@ -145,8 +157,8 @@ add_test(function test_do_log_capture_resilient_readLogFile() {
throw new Error("Exception during readLogFile for: " + loc);
};
// Fire a devicemotion event that is of shake magnitude
sendDeviceMotionEvent(9001, 9001, 9001);
// Fire a series of events that would normally be a shake
sendSustainedShake();
ok(readLocations.length > 0,
"LogShake should attempt to read at least one log");
@ -168,8 +180,8 @@ add_test(function test_do_log_capture_resilient_parseLog() {
return null;
};
// Fire a devicemotion event that is of shake magnitude
sendDeviceMotionEvent(9001, 9001, 9001);
// Fire a series of events that would normally be a shake
sendSustainedShake();
ok(readLocations.length > 0,
"LogShake should attempt to read at least one log");
@ -178,7 +190,29 @@ add_test(function test_do_log_capture_resilient_parseLog() {
run_next_test();
});
add_test(function test_do_nothing_when_dropped() {
// Enable LogShake
LogShake.init();
let readLocations = mockReadLogFile();
// We want a series of spikes to be ignored by LogShake. This roughly
// corresponds to the compare_stairs_sock graph on bug #1101994
for (let i = 0; i < 10 * EVENTS_PER_SECOND; i++) {
// Fire a devicemotion event that is at rest
sendDeviceMotionEvent(0, 0, GRAVITY);
// Fire a spike of motion
sendDeviceMotionEvent(0, 2 * GRAVITY, 2 * GRAVITY);
}
ok(readLocations.length === 0,
"LogShake should not read any logs");
LogShake.uninit();
run_next_test();
});
function run_test() {
debug("Starting");
run_next_test();
}