device: Expose finger status as DBus properties

libfprint v1.90.4 introduced a new finger status API to expose to the UI
the finger status on sensor.

Add two new properties to the Device interface that represent the
possible values.

Add new tests.
This commit is contained in:
Marco Trevisan (Treviño)
2020-12-05 06:19:06 +01:00
committed by Benjamin Berg
parent 30eaaf2def
commit 1835d99265
4 changed files with 172 additions and 4 deletions

View File

@ -64,7 +64,7 @@ add_project_arguments(common_cflags, language: 'c')
host_system = host_machine.system() host_system = host_machine.system()
# NOTE: Bump gdbus-codegen min version once we can depend on 2.64! # NOTE: Bump gdbus-codegen min version once we can depend on 2.64!
glib_min_version = '2.56' glib_min_version = '2.56'
libfprint_min_version = '1.90.1' libfprint_min_version = '1.90.4'
fprintd_installdir = get_option('prefix') / get_option('libexecdir') fprintd_installdir = get_option('prefix') / get_option('libexecdir')
fprintd_plugindir = get_option('prefix') / get_option('libdir') / meson.project_name() / 'modules' fprintd_plugindir = get_option('prefix') / get_option('libdir') / meson.project_name() / 'modules'

View File

@ -327,6 +327,24 @@ on_scan_type_changed (FprintDevice *rdev,
fprint_dbus_device_get_scan_type (dbus_dev)); fprint_dbus_device_get_scan_type (dbus_dev));
} }
static void
on_finger_status_changed (FprintDevice *rdev,
GParamSpec *spec,
FpDevice *device)
{
FprintDBusDevice *dbus_dev = FPRINT_DBUS_DEVICE (rdev);
FpFingerStatusFlags finger_status = fp_device_get_finger_status (device);
gboolean present, needed;
present = !!(finger_status & FP_FINGER_STATUS_PRESENT);
fprint_dbus_device_set_finger_present (dbus_dev, present);
g_debug ("Finger present %d", present);
needed = !!(finger_status & FP_FINGER_STATUS_NEEDED);
fprint_dbus_device_set_finger_needed (dbus_dev, needed);
g_debug ("Finger needed %d", needed);
}
static void static void
fprint_device_constructed (GObject *object) fprint_device_constructed (GObject *object)
{ {
@ -346,6 +364,11 @@ fprint_device_constructed (GObject *object)
rdev, G_CONNECT_SWAPPED); rdev, G_CONNECT_SWAPPED);
on_nr_enroll_stages_changed (rdev, NULL, priv->dev); on_nr_enroll_stages_changed (rdev, NULL, priv->dev);
g_signal_connect_object (priv->dev, "notify::finger-status",
G_CALLBACK (on_finger_status_changed),
rdev, G_CONNECT_SWAPPED);
on_finger_status_changed (rdev, NULL, priv->dev);
G_OBJECT_CLASS (fprint_device_parent_class)->constructed (object); G_OBJECT_CLASS (fprint_device_parent_class)->constructed (object);
} }

View File

@ -573,6 +573,30 @@
</doc:doc> </doc:doc>
</property> </property>
<!-- ************************************************************ -->
<property name="finger-present" type="b" access="read">
<doc:doc>
<doc:description>
<doc:para>
Whether the finger is on sensor.
</doc:para>
</doc:description>
</doc:doc>
</property>
<!-- ************************************************************ -->
<property name="finger-needed" type="b" access="read">
<doc:doc>
<doc:description>
<doc:para>
Whether the sensor is waiting for the finger.
</doc:para>
</doc:description>
</doc:doc>
</property>
</interface> </interface>
</node> </node>

View File

@ -297,6 +297,14 @@ class FPrintdTest(dbusmock.DBusTestCase):
return self.assertRaisesRegex(GLib.Error, return self.assertRaisesRegex(GLib.Error,
'.*net\.reactivated\.Fprint\.Error\.{}.*'.format(fprint_error)) '.*net\.reactivated\.Fprint\.Error\.{}.*'.format(fprint_error))
@property
def finger_needed(self):
return self.device.get_cached_property('finger-needed').unpack()
@property
def finger_present(self):
return self.device.get_cached_property('finger-present').unpack()
# From libfprint tests # From libfprint tests
def send_retry(self, retry_error=FPrint.DeviceRetry.TOO_SHORT, con=None): def send_retry(self, retry_error=FPrint.DeviceRetry.TOO_SHORT, con=None):
if con: if con:
@ -350,7 +358,7 @@ class FPrintdTest(dbusmock.DBusTestCase):
with Connection(self.sockaddr) as con: with Connection(self.sockaddr) as con:
self.send_finger_automatic(automatic, con=con) self.send_finger_automatic(automatic, con=con)
def send_finger_report(self, has_finger, con=None): def send_finger_report(self, has_finger, con=None, iterate=True):
# Send finger on/off # Send finger on/off
if con: if con:
con.sendall(struct.pack('ii', -4, 1 if has_finger else 0)) con.sendall(struct.pack('ii', -4, 1 if has_finger else 0))
@ -359,6 +367,9 @@ class FPrintdTest(dbusmock.DBusTestCase):
with Connection(self.sockaddr) as con: with Connection(self.sockaddr) as con:
self.send_finger_report(has_finger, con=con) self.send_finger_report(has_finger, con=con)
while iterate and self.finger_present != has_finger:
ctx.iteration(False)
def call_device_method_async(self, method, *args): def call_device_method_async(self, method, *args):
""" add cancellable... """ """ add cancellable... """
self.device.call(method, GLib.Variant(*args), self.device.call(method, GLib.Variant(*args),
@ -444,11 +455,19 @@ class FPrintdVirtualDeviceBaseTest(FPrintdTest):
self._abort = True self._abort = True
self._last_result = 'Unexpected signal' self._last_result = 'Unexpected signal'
self.g_signal_id = self.device.connect('g-signal', signal_cb) def property_cb(proxy, changed, invalidated):
print('Changed properties', changed, 'invalidated', invalidated)
self._changed_properties.append(changed.unpack())
signal_id = self.device.connect('g-signal', signal_cb)
self.addCleanup(self.device.disconnect, signal_id)
signal_id = self.device.connect('g-properties-changed', property_cb)
self.addCleanup(self.device.disconnect, signal_id)
self._changed_properties = []
def tearDown(self): def tearDown(self):
self.polkitd_stop() self.polkitd_stop()
self.device.disconnect(self.g_signal_id)
self.device = None self.device = None
self.manager = None self.manager = None
@ -470,6 +489,10 @@ class FPrintdVirtualDeviceBaseTest(FPrintdTest):
device = self.device device = self.device
device.EnrollStart('(s)', finger) device.EnrollStart('(s)', finger)
while not self.finger_needed:
ctx.iteration(False)
self.assertTrue(self.finger_needed)
stages = device.get_cached_property('num-enroll-stages').unpack() stages = device.get_cached_property('num-enroll-stages').unpack()
for stage in range(stages): for stage in range(stages):
self.send_image(img) self.send_image(img)
@ -477,9 +500,11 @@ class FPrintdVirtualDeviceBaseTest(FPrintdTest):
self.wait_for_result('enroll-stage-passed') self.wait_for_result('enroll-stage-passed')
else: else:
self.wait_for_result(expected_result) self.wait_for_result(expected_result)
self.assertFalse(self.finger_needed)
device.EnrollStop() device.EnrollStop()
self.assertEqual(self._last_result, expected_result) self.assertEqual(self._last_result, expected_result)
self.assertFalse(self.finger_needed)
def enroll_multiple_images(self, images_override={}, return_index=-1): def enroll_multiple_images(self, images_override={}, return_index=-1):
enroll_map = { enroll_map = {
@ -781,6 +806,12 @@ class FPrintdVirtualDeviceTest(FPrintdVirtualDeviceBaseTest):
self.assertEqual(self.device.get_cached_property('scan-type').unpack(), self.assertEqual(self.device.get_cached_property('scan-type').unpack(),
'swipe') 'swipe')
def test_initial_finger_needed(self):
self.assertFalse(self.finger_needed)
def test_initial_finger_needed(self):
self.assertFalse(self.finger_present)
def test_allowed_claim_release_enroll(self): def test_allowed_claim_release_enroll(self):
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername', self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername',
'net.reactivated.fprint.device.enroll']) 'net.reactivated.fprint.device.enroll'])
@ -1108,6 +1139,12 @@ class FPrintdVirtualDeviceClaimedTest(FPrintdVirtualDeviceBaseTest):
# Finger is enrolled, try to verify it # Finger is enrolled, try to verify it
self.device.VerifyStart('(s)', 'any') self.device.VerifyStart('(s)', 'any')
while not self.finger_needed:
ctx.iteration(True)
self.assertTrue(self.finger_needed)
self.assertFalse(self.finger_present)
# Try a wrong print; will stop verification # Try a wrong print; will stop verification
self.send_image('tented_arch') self.send_image('tented_arch')
self.wait_for_result() self.wait_for_result()
@ -1406,6 +1443,90 @@ class FPrintdVirtualDeviceClaimedTest(FPrintdVirtualDeviceBaseTest):
with self.assertFprintError('AlreadyInUse'): with self.assertFprintError('AlreadyInUse'):
self.call_device_method_from_other_client('VerifyStart', ['left-thumb']) self.call_device_method_from_other_client('VerifyStart', ['left-thumb'])
def test_enroll_finger_status(self):
self.assertFalse(self.finger_present)
self.assertFalse(self.finger_needed)
self.device.EnrollStart('(s)', 'right-middle-finger')
self.assertEqual(self._changed_properties, [])
while not self.finger_needed:
ctx.iteration(False)
self.assertIn({'finger-needed': True}, self._changed_properties)
self.assertTrue(self.finger_needed)
self.assertFalse(self.finger_present)
self._changed_properties = []
self.send_finger_report(True)
self.assertEqual([{'finger-present': True}], self._changed_properties)
self.assertTrue(self.finger_needed)
self.assertTrue(self.finger_present)
self._changed_properties = []
self.send_finger_report(False)
self.assertFalse(self.finger_present)
self.assertTrue(self.finger_needed)
self.assertEqual([{'finger-present': False}], self._changed_properties)
self._changed_properties = []
self.device.EnrollStop()
while self.finger_needed:
ctx.iteration(False)
self.assertFalse(self.finger_present)
self.assertFalse(self.finger_needed)
self.assertEqual([{'finger-needed': False}], self._changed_properties)
def test_verify_finger_status(self):
self.assertFalse(self.finger_present)
self.assertFalse(self.finger_needed)
self.assertEqual(self._changed_properties, [])
self.enroll_image('whorl')
self.assertIn({'finger-needed': True}, self._changed_properties)
self.assertIn({'finger-needed': False}, self._changed_properties)
self.assertFalse(self.finger_present)
self.assertFalse(self.finger_needed)
self._changed_properties = []
self.device.VerifyStart('(s)', 'any')
self.assertEqual(self._changed_properties, [])
while not self.finger_needed:
ctx.iteration(False)
self.assertIn({'finger-needed': True}, self._changed_properties)
self.assertTrue(self.finger_needed)
self.assertFalse(self.finger_present)
self._changed_properties = []
self.send_finger_report(True)
self.assertEqual([{'finger-present': True}], self._changed_properties)
self.assertTrue(self.finger_needed)
self.assertTrue(self.finger_present)
self._changed_properties = []
self.send_finger_report(False)
self.assertFalse(self.finger_present)
self.assertTrue(self.finger_needed)
self.assertEqual([{'finger-present': False}], self._changed_properties)
self._changed_properties = []
self.device.VerifyStop()
while self.finger_needed:
ctx.iteration(False)
self.assertFalse(self.finger_present)
self.assertFalse(self.finger_needed)
self.assertEqual([{'finger-needed': False}], self._changed_properties)
class FPrintdVirtualDeviceEnrollTests(FPrintdVirtualDeviceBaseTest): class FPrintdVirtualDeviceEnrollTests(FPrintdVirtualDeviceBaseTest):