virtual-device: Make possible to inject sleep events while verifying/identifying

Each command should be separated by SLEEP to be considered as something
we want to perform during the current operation, otherwise will be used
by next operation consuming it.
This commit is contained in:
Marco Trevisan (Treviño) 2021-01-26 03:37:16 +01:00
parent 1dae6796f7
commit 7ffcc2f9e7
4 changed files with 110 additions and 8 deletions

View file

@ -80,7 +80,9 @@ struct _FpDeviceVirtualDevice
guint wait_command_id; guint wait_command_id;
guint sleep_timeout_id; guint sleep_timeout_id;
guint enroll_stages_passed; guint enroll_stages_passed;
gboolean match_reported;
gboolean supports_cancellation; gboolean supports_cancellation;
gboolean injected_synthetic_cmd;
}; };
/* Not really final here, but we can do this to share the FpDeviceVirtualDevice /* Not really final here, but we can do this to share the FpDeviceVirtualDevice
@ -100,3 +102,6 @@ char * start_scan_command (FpDeviceVirtualDevice *self,
GError **error); GError **error);
gboolean should_wait_for_command (FpDeviceVirtualDevice *self, gboolean should_wait_for_command (FpDeviceVirtualDevice *self,
GError *error); GError *error);
gboolean should_wait_to_sleep (FpDeviceVirtualDevice *self,
const char *scan_id,
GError *error);

View file

@ -69,10 +69,14 @@ dev_identify (FpDevice *dev)
&idx)) &idx))
match = g_ptr_array_index (prints, idx); match = g_ptr_array_index (prints, idx);
fpi_device_identify_report (dev, if (!self->match_reported)
match, {
new_scan, self->match_reported = TRUE;
NULL); fpi_device_identify_report (dev,
match,
new_scan,
NULL);
}
} }
else if (error && error->domain == FP_DEVICE_RETRY) else if (error && error->domain == FP_DEVICE_RETRY)
{ {
@ -83,6 +87,10 @@ dev_identify (FpDevice *dev)
FP_FINGER_STATUS_NONE, FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT); FP_FINGER_STATUS_PRESENT);
if (should_wait_to_sleep (self, scan_id, error))
return;
self->match_reported = FALSE;
fpi_device_identify_complete (dev, g_steal_pointer (&error)); fpi_device_identify_complete (dev, g_steal_pointer (&error));
} }

View file

@ -53,6 +53,9 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self)
{ {
FpDevice *dev = FP_DEVICE (self); FpDevice *dev = FP_DEVICE (self);
if (self->sleep_timeout_id)
return;
switch (fpi_device_get_current_action (dev)) switch (fpi_device_get_current_action (dev))
{ {
case FPI_DEVICE_ACTION_ENROLL: case FPI_DEVICE_ACTION_ENROLL:
@ -365,6 +368,9 @@ start_scan_command (FpDeviceVirtualDevice *self,
g_autoptr(GError) local_error = NULL; g_autoptr(GError) local_error = NULL;
g_autofree char *scan_id = NULL; g_autofree char *scan_id = NULL;
if (fp_device_get_finger_status (FP_DEVICE (self)) == FP_FINGER_STATUS_NONE)
self->injected_synthetic_cmd = FALSE;
scan_id = process_cmds (self, TRUE, &local_error); scan_id = process_cmds (self, TRUE, &local_error);
if (!self->sleep_timeout_id) if (!self->sleep_timeout_id)
@ -376,6 +382,8 @@ start_scan_command (FpDeviceVirtualDevice *self,
if (should_wait_for_command (self, local_error)) if (should_wait_for_command (self, local_error))
{ {
g_assert (!scan_id);
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING, g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
"Still waiting for command"); "Still waiting for command");
return NULL; return NULL;
@ -391,6 +399,51 @@ start_scan_command (FpDeviceVirtualDevice *self,
return g_steal_pointer (&scan_id); return g_steal_pointer (&scan_id);
} }
gboolean
should_wait_to_sleep (FpDeviceVirtualDevice *self,
const char *scan_id,
GError *error)
{
const gchar *cmd;
if (self->sleep_timeout_id)
return TRUE;
if (!self->pending_commands->len)
return FALSE;
cmd = g_ptr_array_index (self->pending_commands, 0);
if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX))
{
g_free (process_cmds (self, FALSE, NULL));
g_assert (!self->injected_synthetic_cmd);
g_assert (self->sleep_timeout_id != 0);
if (!self->pending_commands->len)
{
g_autofree char *injected_cmd = NULL;
if (scan_id)
injected_cmd = g_strconcat (SCAN_CMD_PREFIX, scan_id, NULL);
else if (error && error->domain == FP_DEVICE_ERROR)
injected_cmd = g_strdup_printf (ERROR_CMD_PREFIX " %d", error->code);
else if (error && error->domain == FP_DEVICE_RETRY)
injected_cmd = g_strdup_printf (RETRY_CMD_PREFIX " %d", error->code);
else
return TRUE;
g_debug ("Sleeping now, command queued for later: %s", injected_cmd);
g_ptr_array_insert (self->pending_commands, 0, g_steal_pointer (&injected_cmd));
self->injected_synthetic_cmd = TRUE;
}
}
return self->sleep_timeout_id != 0;
}
static void static void
dev_verify (FpDevice *dev) dev_verify (FpDevice *dev)
{ {
@ -422,10 +475,14 @@ dev_verify (FpDevice *dev)
success = fp_print_equal (print, new_scan); success = fp_print_equal (print, new_scan);
fpi_device_verify_report (dev, if (!self->match_reported)
success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL, {
new_scan, self->match_reported = TRUE;
NULL); fpi_device_verify_report (dev,
success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL,
new_scan,
NULL);
}
} }
else else
{ {
@ -439,6 +496,10 @@ dev_verify (FpDevice *dev)
if (error && error->domain == FP_DEVICE_RETRY) if (error && error->domain == FP_DEVICE_RETRY)
fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error)); fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error));
if (should_wait_to_sleep (self, scan_id, error))
return;
self->match_reported = FALSE;
fpi_device_verify_complete (dev, g_steal_pointer (&error)); fpi_device_verify_complete (dev, g_steal_pointer (&error));
} }
@ -517,6 +578,9 @@ dev_enroll (FpDevice *dev)
} }
else else
{ {
if (should_wait_to_sleep (self, id, error))
return;
self->enroll_stages_passed = 0; self->enroll_stages_passed = 0;
fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error)); fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error));
} }
@ -528,6 +592,12 @@ dev_cancel (FpDevice *dev)
{ {
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
if (self->injected_synthetic_cmd)
{
self->injected_synthetic_cmd = FALSE;
g_ptr_array_remove_index (self->pending_commands, 0);
}
if (!self->supports_cancellation) if (!self->supports_cancellation)
return; return;

View file

@ -526,6 +526,25 @@ class VirtualDevice(unittest.TestCase):
self.assertFalse(self._verify_completed) self.assertFalse(self._verify_completed)
self.cancel_verify() self.cancel_verify()
def test_device_sleep_before_completing_verify(self):
enrolled = self.enroll_print('foo-print', FPrint.Finger.LEFT_RING)
self.send_command('SLEEP', 100)
self.start_verify(enrolled, identify=self.dev.supports_identify())
self.send_command('SCAN', 'bar-print')
self.send_command('SLEEP', 800)
while not self._verify_reported:
ctx.iteration(False)
self.assertFalse(self._verify_completed)
self.wait_timeout(10)
self.assertFalse(self._verify_completed)
self.complete_verify()
self.assertTrue(self._verify_reported)
class VirtualDeviceStorage(VirtualDevice): class VirtualDeviceStorage(VirtualDevice):
def tearDown(self): def tearDown(self):