virtual-device: Add SET_KEEP_ALIVE command, to keep the listener up
We may want to be able to talk with the device while it's closed to queue commands to be performed once it opens (could be even a script), so to do this we need to close the device first, send those commands and eventually process them. We used a trick to send an invalid command before that was ignored by release, but having the device available is just easier to handle. So, when keep alive is enabled we don't stop the listener when closing but only on actual device disposition.
This commit is contained in:
parent
2f7c78eb97
commit
27a62443a1
3 changed files with 64 additions and 11 deletions
|
@ -84,6 +84,7 @@ struct _FpDeviceVirtualDevice
|
|||
gboolean supports_cancellation;
|
||||
gboolean injected_synthetic_cmd;
|
||||
gboolean ignore_wait;
|
||||
gboolean keep_alive;
|
||||
};
|
||||
|
||||
/* Not really final here, but we can do this to share the FpDeviceVirtualDevice
|
||||
|
|
|
@ -44,6 +44,7 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE)
|
|||
#define SET_ENROLL_STAGES_PREFIX "SET_ENROLL_STAGES "
|
||||
#define SET_SCAN_TYPE_PREFIX "SET_SCAN_TYPE "
|
||||
#define SET_CANCELLATION_PREFIX "SET_CANCELLATION_ENABLED "
|
||||
#define SET_KEEP_ALIVE_PREFIX "SET_KEEP_ALIVE "
|
||||
|
||||
#define LIST_CMD "LIST"
|
||||
#define UNPLUG_CMD "UNPLUG"
|
||||
|
@ -289,6 +290,13 @@ recv_instruction_cb (GObject *source_object,
|
|||
g_debug ("Cancellation support toggled: %d",
|
||||
self->supports_cancellation);
|
||||
}
|
||||
else if (g_str_has_prefix (cmd, SET_KEEP_ALIVE_PREFIX))
|
||||
{
|
||||
self->keep_alive = g_ascii_strtoull (
|
||||
cmd + strlen (SET_KEEP_ALIVE_PREFIX), NULL, 10) != 0;
|
||||
|
||||
g_debug ("Keep alive toggled: %d", self->keep_alive);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ptr_array_add (self->pending_commands, g_steal_pointer (&cmd));
|
||||
|
@ -692,6 +700,14 @@ dev_cancel (FpDevice *dev)
|
|||
maybe_continue_current_action (self);
|
||||
}
|
||||
|
||||
static void
|
||||
stop_listener (FpDeviceVirtualDevice *self)
|
||||
{
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
g_clear_object (&self->cancellable);
|
||||
g_clear_object (&self->listener);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_deinit (FpDevice *dev)
|
||||
{
|
||||
|
@ -711,10 +727,9 @@ dev_deinit (FpDevice *dev)
|
|||
|
||||
g_clear_handle_id (&self->wait_command_id, g_source_remove);
|
||||
g_clear_handle_id (&self->sleep_timeout_id, g_source_remove);
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
g_clear_object (&self->cancellable);
|
||||
g_clear_object (&self->listener);
|
||||
g_clear_object (&self->listener);
|
||||
|
||||
if (!self->keep_alive)
|
||||
stop_listener (self);
|
||||
|
||||
fpi_device_close_complete (dev, NULL);
|
||||
}
|
||||
|
@ -725,6 +740,7 @@ fpi_device_virtual_device_finalize (GObject *object)
|
|||
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (object);
|
||||
|
||||
G_DEBUG_HERE ();
|
||||
stop_listener (self);
|
||||
g_clear_pointer (&self->pending_commands, g_ptr_array_unref);
|
||||
G_OBJECT_CLASS (fpi_device_virtual_device_parent_class)->finalize (object);
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ class VirtualDeviceBase(unittest.TestCase):
|
|||
def send_command(self, command, *args):
|
||||
self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY',
|
||||
'FINGER', 'UNPLUG', 'SLEEP', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE',
|
||||
'SET_CANCELLATION_ENABLED', 'IGNORED_COMMAND'])
|
||||
'SET_CANCELLATION_ENABLED', 'SET_KEEP_ALIVE', 'IGNORED_COMMAND'])
|
||||
|
||||
with Connection(self.sockaddr) as con:
|
||||
params = ' '.join(str(p) for p in args)
|
||||
|
@ -162,6 +162,9 @@ class VirtualDeviceBase(unittest.TestCase):
|
|||
else:
|
||||
raise Exception('No known type found for {}'.format(obj))
|
||||
|
||||
def set_keep_alive(self, value):
|
||||
self.send_command('SET_KEEP_ALIVE', 1 if value else 0)
|
||||
|
||||
def send_sleep(self, interval):
|
||||
self.assertGreater(interval, 0)
|
||||
multiplier = 5 if 'UNDER_VALGRIND' in os.environ else 1
|
||||
|
@ -361,6 +364,17 @@ class VirtualDevice(VirtualDeviceBase):
|
|||
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
|
||||
FPrint.DeviceError.PROTO))
|
||||
|
||||
def test_open_error_with_keep_alive(self):
|
||||
self._close_on_teardown = False
|
||||
self.set_keep_alive(True)
|
||||
self.dev.close_sync()
|
||||
|
||||
self.send_error(FPrint.DeviceError.PROTO)
|
||||
with self.assertRaises(GLib.Error) as error:
|
||||
self.dev.open_sync()
|
||||
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
|
||||
FPrint.DeviceError.PROTO))
|
||||
|
||||
def test_delayed_open(self):
|
||||
self.send_command('IGNORED_COMMAND') # This will be consumed by close
|
||||
self.send_sleep(500) # This will be consumed by open
|
||||
|
@ -386,6 +400,28 @@ class VirtualDevice(VirtualDeviceBase):
|
|||
while not opened:
|
||||
ctx.iteration(True)
|
||||
|
||||
def test_delayed_open_with_keep_alive(self):
|
||||
self.set_keep_alive(True)
|
||||
self.dev.close_sync()
|
||||
|
||||
opened = False
|
||||
def on_opened(dev, res):
|
||||
nonlocal opened
|
||||
dev.open_finish(res)
|
||||
opened = True
|
||||
|
||||
self.send_sleep(500)
|
||||
self.dev.open(callback=on_opened)
|
||||
|
||||
self.wait_timeout(10)
|
||||
self.assertFalse(self.dev.is_open())
|
||||
|
||||
self.wait_timeout(10)
|
||||
self.assertFalse(self.dev.is_open())
|
||||
|
||||
while not opened:
|
||||
ctx.iteration(True)
|
||||
|
||||
def test_enroll(self):
|
||||
matching = self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE)
|
||||
self.assertEqual(matching.get_username(), 'testuser')
|
||||
|
@ -485,6 +521,7 @@ class VirtualDevice(VirtualDeviceBase):
|
|||
ctx.iteration(True)
|
||||
|
||||
self.assertEqual(enrolled.get_driver(), self.dev.get_driver())
|
||||
self.assertEqual(enrolled.props.fpi_data.unpack(), 'print-id')
|
||||
|
||||
def test_enroll_script(self):
|
||||
self.send_command('SET_ENROLL_STAGES', 8)
|
||||
|
@ -507,6 +544,7 @@ class VirtualDevice(VirtualDeviceBase):
|
|||
|
||||
enrolled = self.dev.enroll_sync(FPrint.Print.new(self.dev))
|
||||
self.assertEqual(enrolled.get_driver(), self.dev.get_driver())
|
||||
self.assertEqual(enrolled.props.fpi_data.unpack(), 'print-id')
|
||||
|
||||
def test_finger_status(self):
|
||||
self.start_verify(FPrint.Print.new(self.dev),
|
||||
|
@ -812,15 +850,13 @@ class VirtualDeviceBusyDeviceOperations(VirtualDeviceBase):
|
|||
super().tearDown()
|
||||
|
||||
def test_open(self):
|
||||
self.send_command('IGNORED_COMMAND')
|
||||
self.send_sleep(100)
|
||||
self.set_keep_alive(True)
|
||||
|
||||
with GLibErrorMessage('libfprint-virtual_device',
|
||||
GLib.LogLevelFlags.LEVEL_WARNING, 'Could not process command: *'):
|
||||
while self.dev.is_open():
|
||||
ctx.iteration(True)
|
||||
while self.dev.is_open():
|
||||
ctx.iteration(True)
|
||||
|
||||
self.assertFalse(self.dev.is_open())
|
||||
self.send_sleep(100)
|
||||
self.dev.open()
|
||||
with self.assertRaises(GLib.Error) as error:
|
||||
self.dev.open_sync()
|
||||
|
|
Loading…
Reference in a new issue