mirror of
https://gitlab.gnome.org/GNOME/calls.git
synced 2024-12-04 20:07:36 +00:00
Resolve emergency number types
We add a small hardcoded table for now. Future versions will improve this to parse this out of ASOPs eccdata. If we can't determine the type of a number we add it verbatim.
This commit is contained in:
parent
9f68e242fd
commit
b087bea16b
7 changed files with 211 additions and 4 deletions
|
@ -8,6 +8,7 @@ src/calls-account-overview.c
|
||||||
src/calls-application.c
|
src/calls-application.c
|
||||||
src/calls-best-match.c
|
src/calls-best-match.c
|
||||||
src/calls-call-record-row.c
|
src/calls-call-record-row.c
|
||||||
|
src/calls-emergency-call-types.c
|
||||||
src/calls-main-window.c
|
src/calls-main-window.c
|
||||||
src/calls-notifier.c
|
src/calls-notifier.c
|
||||||
src/ui/account-overview.ui
|
src/ui/account-overview.ui
|
||||||
|
|
107
src/calls-emergency-call-types.c
Normal file
107
src/calls-emergency-call-types.c
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Purism SPC
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* Author: Guido Günther <agx@sigxcpu.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define G_LOG_DOMAIN "CallsEmergencyCallType"
|
||||||
|
|
||||||
|
#include "calls-emergency-call-types.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:calls-emergency-call-type
|
||||||
|
* @short_description: Emergency call types per country
|
||||||
|
*
|
||||||
|
* Exerpt from https://source.android.com/docs/core/connect/emergency-number-db
|
||||||
|
* TODO: parse the actual database for dynamic updates and broader coverage
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *number;
|
||||||
|
CallsEmergencyCallTypeFlags flags;
|
||||||
|
} CallsEmergencyNumber;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *country_code;
|
||||||
|
CallsEmergencyNumber numbers[3];
|
||||||
|
} CallsEmergencyNumberTypes;
|
||||||
|
|
||||||
|
CallsEmergencyNumberTypes emergency_number_types[] = {
|
||||||
|
{ "CH",
|
||||||
|
{
|
||||||
|
{ "117", CALLS_EMERGENCY_CALL_TYPE_POLICE },
|
||||||
|
{ "144", CALLS_EMERGENCY_CALL_TYPE_AMBULANCE },
|
||||||
|
{ "118", CALLS_EMERGENCY_CALL_TYPE_FIRE_BRIGADE }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ "DE",
|
||||||
|
{
|
||||||
|
{ "112", (CALLS_EMERGENCY_CALL_TYPE_POLICE |
|
||||||
|
CALLS_EMERGENCY_CALL_TYPE_AMBULANCE |
|
||||||
|
CALLS_EMERGENCY_CALL_TYPE_FIRE_BRIGADE) }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ "US",
|
||||||
|
{
|
||||||
|
{ "911", (CALLS_EMERGENCY_CALL_TYPE_POLICE |
|
||||||
|
CALLS_EMERGENCY_CALL_TYPE_AMBULANCE |
|
||||||
|
CALLS_EMERGENCY_CALL_TYPE_FIRE_BRIGADE) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
flags_to_string (CallsEmergencyCallTypeFlags flags)
|
||||||
|
{
|
||||||
|
g_autoptr (GPtrArray) types = g_ptr_array_new ();
|
||||||
|
|
||||||
|
if (flags & CALLS_EMERGENCY_CALL_TYPE_POLICE) {
|
||||||
|
g_ptr_array_add (types, _("Police"));
|
||||||
|
}
|
||||||
|
if (flags & CALLS_EMERGENCY_CALL_TYPE_AMBULANCE) {
|
||||||
|
g_ptr_array_add (types, _("Ambulance"));
|
||||||
|
}
|
||||||
|
if (flags & CALLS_EMERGENCY_CALL_TYPE_FIRE_BRIGADE) {
|
||||||
|
g_ptr_array_add (types, _("Fire Brigade"));
|
||||||
|
}
|
||||||
|
if (flags & CALLS_EMERGENCY_CALL_TYPE_MOUNTAIN_RESCUE) {
|
||||||
|
g_ptr_array_add (types, _("Mountain Rescue"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (types->len == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
g_ptr_array_add (types, NULL);
|
||||||
|
/* TODO: join in RTL and locale aware way */
|
||||||
|
return g_strjoinv (", ", (GStrv)types->pdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
calls_emergency_call_type_get_name (const char *lookup, const char *country_code)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (lookup, NULL);
|
||||||
|
if (country_code == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < G_N_ELEMENTS (emergency_number_types); i++){
|
||||||
|
CallsEmergencyNumberTypes *numbers = &emergency_number_types[i];
|
||||||
|
|
||||||
|
if (g_str_equal (numbers->country_code, country_code) == FALSE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int n = 0; n < G_N_ELEMENTS (numbers->numbers); n++) {
|
||||||
|
CallsEmergencyNumber *number = &numbers->numbers[n];
|
||||||
|
|
||||||
|
if (g_strcmp0 (lookup, number->number) == 0)
|
||||||
|
return flags_to_string (number->flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
24
src/calls-emergency-call-types.h
Normal file
24
src/calls-emergency-call-types.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Guido Günther
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
# pragma once
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CALLS_EMERGENCY_CONTACT_SOURCE_UNKNOWN = 0,
|
||||||
|
CALLS_EMERGENCY_CONTACT_SOURCE_FALLBACK = (1 << 0),
|
||||||
|
CALLS_EMERGENCY_CONTACT_SOURCE_SIM = (1 << 1),
|
||||||
|
} CallsEmergencyContactSource;
|
||||||
|
|
||||||
|
/* See 3GPP TS 22.101 version 14.8.0 Release 14, Chapter 10.1 */
|
||||||
|
typedef enum {
|
||||||
|
CALLS_EMERGENCY_CALL_TYPE_UNKNOWN = 0,
|
||||||
|
CALLS_EMERGENCY_CALL_TYPE_POLICE = (1 << 0),
|
||||||
|
CALLS_EMERGENCY_CALL_TYPE_AMBULANCE = (1 << 1),
|
||||||
|
CALLS_EMERGENCY_CALL_TYPE_FIRE_BRIGADE = (1 << 2),
|
||||||
|
CALLS_EMERGENCY_CALL_TYPE_MOUNTAIN_RESCUE = (1 << 3),
|
||||||
|
} CallsEmergencyCallTypeFlags;
|
||||||
|
|
||||||
|
char *calls_emergency_call_type_get_name (const char *number, const char *country_code);
|
|
@ -9,6 +9,7 @@
|
||||||
#define G_LOG_DOMAIN "CallsEmergencyCallsManger"
|
#define G_LOG_DOMAIN "CallsEmergencyCallsManger"
|
||||||
|
|
||||||
#include "calls-emergency-calls-manager.h"
|
#include "calls-emergency-calls-manager.h"
|
||||||
|
#include "calls-emergency-call-types.h"
|
||||||
#include "calls-origin.h"
|
#include "calls-origin.h"
|
||||||
#include "calls-manager.h"
|
#include "calls-manager.h"
|
||||||
|
|
||||||
|
@ -29,7 +30,6 @@ typedef struct _CallsEmergencyCallsManager
|
||||||
} CallsEmergencyCallsManger;
|
} CallsEmergencyCallsManger;
|
||||||
|
|
||||||
static void calls_emergency_calls_iface_init (CallsDBusEmergencyCallsIface *iface);
|
static void calls_emergency_calls_iface_init (CallsDBusEmergencyCallsIface *iface);
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (CallsEmergencyCallsManager,
|
G_DEFINE_TYPE_WITH_CODE (CallsEmergencyCallsManager,
|
||||||
calls_emergency_calls_manager,
|
calls_emergency_calls_manager,
|
||||||
CALLS_DBUS_TYPE_EMERGENCY_CALLS_SKELETON,
|
CALLS_DBUS_TYPE_EMERGENCY_CALLS_SKELETON,
|
||||||
|
@ -90,18 +90,26 @@ handle_get_emergency_contacts (CallsDBusEmergencyCalls *object,
|
||||||
for (int i = 0; i < g_list_model_get_n_items (self->origins); i++) {
|
for (int i = 0; i < g_list_model_get_n_items (self->origins); i++) {
|
||||||
CallsOrigin *origin = g_list_model_get_item (self->origins, i);
|
CallsOrigin *origin = g_list_model_get_item (self->origins, i);
|
||||||
g_auto (GStrv) emergency_numbers = NULL;
|
g_auto (GStrv) emergency_numbers = NULL;
|
||||||
|
const char *country_code;
|
||||||
|
|
||||||
emergency_numbers = calls_origin_get_emergency_numbers (origin);
|
emergency_numbers = calls_origin_get_emergency_numbers (origin);
|
||||||
if (!emergency_numbers)
|
if (!emergency_numbers)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
country_code = calls_origin_get_country_code (origin);
|
||||||
for (int j = 0; j < g_strv_length (emergency_numbers); j++) {
|
for (int j = 0; j < g_strv_length (emergency_numbers); j++) {
|
||||||
|
g_autofree char *contact = NULL;
|
||||||
|
|
||||||
g_variant_builder_open (&contacts_builder, G_VARIANT_TYPE (CONTACT_FORMAT));
|
g_variant_builder_open (&contacts_builder, G_VARIANT_TYPE (CONTACT_FORMAT));
|
||||||
g_variant_builder_add (&contacts_builder, "s", emergency_numbers[j]);
|
g_variant_builder_add (&contacts_builder, "s", emergency_numbers[j]);
|
||||||
/* For non-addressbook numbers we just use the number itself as contact */
|
|
||||||
g_variant_builder_add (&contacts_builder, "s", emergency_numbers[j]);
|
contact = calls_emergency_call_type_get_name (emergency_numbers[j], country_code);
|
||||||
|
if (contact == NULL)
|
||||||
|
contact = g_strdup (emergency_numbers[j]);
|
||||||
|
g_variant_builder_add (&contacts_builder, "s", contact);
|
||||||
/* Currently unused */
|
/* Currently unused */
|
||||||
g_variant_builder_add (&contacts_builder, "i", 0);
|
g_variant_builder_add (&contacts_builder, "i",
|
||||||
|
CALLS_EMERGENCY_CONTACT_SOURCE_UNKNOWN);
|
||||||
/* Currently no hints */
|
/* Currently no hints */
|
||||||
g_variant_builder_add (&contacts_builder, "a{sv}", NULL);
|
g_variant_builder_add (&contacts_builder, "a{sv}", NULL);
|
||||||
g_variant_builder_close (&contacts_builder);
|
g_variant_builder_close (&contacts_builder);
|
||||||
|
|
|
@ -102,6 +102,7 @@ calls_sources = files([
|
||||||
'calls-contacts-row.c', 'calls-contacts-row.h',
|
'calls-contacts-row.c', 'calls-contacts-row.h',
|
||||||
'calls-dbus-manager.c', 'calls-dbus-manager.h',
|
'calls-dbus-manager.c', 'calls-dbus-manager.h',
|
||||||
'calls-emergency-calls-manager.c', 'calls-emergency-calls-manager.h',
|
'calls-emergency-calls-manager.c', 'calls-emergency-calls-manager.h',
|
||||||
|
'calls-emergency-call-types.c', 'calls-emergency-call-types.h',
|
||||||
'calls-history-box.c', 'calls-history-box.h',
|
'calls-history-box.c', 'calls-history-box.h',
|
||||||
'calls-in-app-notification.c', 'calls-in-app-notification.h',
|
'calls-in-app-notification.c', 'calls-in-app-notification.h',
|
||||||
'calls-log.c', 'calls-log.h',
|
'calls-log.c', 'calls-log.h',
|
||||||
|
|
|
@ -38,6 +38,20 @@ test_includes = include_directories('.')
|
||||||
subdir('mock')
|
subdir('mock')
|
||||||
subdir('services')
|
subdir('services')
|
||||||
|
|
||||||
|
test_sources = [ 'test-emergency-call-types.c' ]
|
||||||
|
t = executable('emergency-call-types', test_sources,
|
||||||
|
c_args : test_cflags,
|
||||||
|
link_args: test_link_args,
|
||||||
|
pie: true,
|
||||||
|
link_with : [calls_vala, libcalls],
|
||||||
|
dependencies: calls_deps,
|
||||||
|
include_directories : [
|
||||||
|
calls_includes,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
test('emergency-call-types', t, env: test_env)
|
||||||
|
|
||||||
|
|
||||||
test_sources = [ 'test-manager.c' ]
|
test_sources = [ 'test-manager.c' ]
|
||||||
|
|
||||||
t = executable('manager', test_sources,
|
t = executable('manager', test_sources,
|
||||||
|
|
52
tests/test-emergency-call-types.c
Normal file
52
tests/test-emergency-call-types.c
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) Guido Günther
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "calls-emergency-call-types.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_lookup (void)
|
||||||
|
{
|
||||||
|
char *lookup = NULL;
|
||||||
|
|
||||||
|
/* No countyr code -> no match */
|
||||||
|
lookup = calls_emergency_call_type_get_name ("112", NULL);
|
||||||
|
g_assert_null (lookup);
|
||||||
|
|
||||||
|
/* Country code that's not in the table */
|
||||||
|
lookup = calls_emergency_call_type_get_name ("112", "doesnotexist");
|
||||||
|
g_assert_null (lookup);
|
||||||
|
|
||||||
|
/* Numbers that match a single type */
|
||||||
|
lookup = calls_emergency_call_type_get_name ("117", "CH");
|
||||||
|
g_assert_cmpstr (lookup, ==, "Police");
|
||||||
|
g_free (lookup);
|
||||||
|
|
||||||
|
lookup = calls_emergency_call_type_get_name ("144", "CH");
|
||||||
|
g_assert_cmpstr (lookup, ==, "Ambulance");
|
||||||
|
g_free (lookup);
|
||||||
|
|
||||||
|
/* Numbers that match multiple types */
|
||||||
|
lookup = calls_emergency_call_type_get_name ("112", "DE");
|
||||||
|
g_assert_cmpstr (lookup, ==, "Police, Ambulance, Fire Brigade");
|
||||||
|
g_free (lookup);
|
||||||
|
|
||||||
|
/* Numbers that doesn't match */
|
||||||
|
lookup = calls_emergency_call_type_get_name ("123456", "DE");
|
||||||
|
g_assert_null (lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
|
g_test_add_func ("/Calls/EmergencyCallTypes/lookup", test_lookup);
|
||||||
|
|
||||||
|
return g_test_run ();
|
||||||
|
}
|
Loading…
Reference in a new issue