From 4e454de545544526cbea9d787df9ba76cb99d889 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Thu, 10 May 2018 12:41:35 -0400 Subject: telephony binding: support runtime change of BT HFP modem The binding currently only queries for a BT HFP enabled modem once at binding init time. To support runtime modem changes, use BT binding events to handle connection and disconnection of BT HFP devices. The default voice call modem is now torn down on device disconnect and initialized when a new BT HFP device is connected at runtime. Bug-AGL: SPEC-1433 Change-Id: Icea7686ef5ecb80b0d33560e4499ca1fd6285147 Signed-off-by: Matt Porter --- package/config.xml | 1 + telephony-binding/gdbus/ofono_manager.c | 28 ------- telephony-binding/telephony-binding.c | 142 ++++++++++++++++++++++++++++---- 3 files changed, 125 insertions(+), 46 deletions(-) diff --git a/package/config.xml b/package/config.xml index ac580f0..183aba1 100644 --- a/package/config.xml +++ b/package/config.xml @@ -10,6 +10,7 @@ + diff --git a/telephony-binding/gdbus/ofono_manager.c b/telephony-binding/gdbus/ofono_manager.c index a77623d..98b0fdc 100644 --- a/telephony-binding/gdbus/ofono_manager.c +++ b/telephony-binding/gdbus/ofono_manager.c @@ -50,7 +50,6 @@ int ofono_manager_set_default_modem(const char *address) gchar *path, *key; const gchar *name = NULL, *type = NULL, *serial = NULL; gboolean powered = FALSE, online = FALSE; - GVariantIter *iter, *iter2 = NULL; int ret = 0; @@ -95,10 +94,6 @@ int ofono_manager_set_default_modem(const char *address) int ofono_manager_init() { - GVariant *out_arg = NULL, *next, *value; - GError *error = NULL; - GVariantIter *iter, *iter2 = NULL; - gchar *path, *key; int ret = 0; if (manager) { @@ -115,29 +110,6 @@ int ofono_manager_init() return -1; } - org_ofono_manager_call_get_modems_sync(manager, &out_arg, NULL, &error); - if (error == NULL) { - g_variant_get(out_arg, "a(oa{sv})", &iter); - next = g_variant_iter_next_value(iter); - if (next) { - g_variant_get(next, "(oa{sv})", &path, &iter2); - default_modem.path = path; - while (g_variant_iter_loop(iter2, "{sv}", &key, &value)) { - if (!strcmp(key, "Name")) - default_modem.name = g_variant_get_string(value, NULL); - else if (!strcmp(key, "Type")) - default_modem.type = g_variant_get_string(value, NULL); - else if (!strcmp(key, "Powered")) - default_modem.powered = g_variant_get_boolean(value); - else if (!strcmp(key, "Online")) - default_modem.online = g_variant_get_boolean(value); - } - } else { - ret = -1; - } - } else { - ret = -1; - } return ret; } diff --git a/telephony-binding/telephony-binding.c b/telephony-binding/telephony-binding.c index 6d8966c..3d0f06a 100644 --- a/telephony-binding/telephony-binding.c +++ b/telephony-binding/telephony-binding.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Konsulko Group + * Copyright (C) 2017-2018 Konsulko Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -178,6 +178,88 @@ static void *main_loop_thread(void *unused) return NULL; } +static int ofono_init_default_modem(void) +{ + int ret = 0; + const gchar *modem_path = ofono_manager_get_default_modem_path(); + + if (modem_path) { + vcm = ofono_voicecallmanager_init(modem_path, + incoming_call_cb, + dialing_call_cb, + terminated_call_cb); + if (!vcm) { + AFB_ERROR("failed to initialize voice call manager\n"); + ret = -1; + } + } else { + AFB_ERROR("default modem not set\n"); + ret = -1; + } + + return ret; +} + +static gboolean is_hfp_dev_and_init(struct json_object *dev) +{ + int ret; + gboolean hfp = FALSE; + struct json_object *name, *address, *hfp_connected; + json_object_object_get_ex(dev, "Name", &name); + json_object_object_get_ex(dev, "Address", &address); + json_object_object_get_ex(dev, "HFPConnected", &hfp_connected); + if (!strcmp(json_object_get_string(hfp_connected), "True")) { + ret = ofono_manager_set_default_modem(json_object_get_string(address)); + if (ret == 0) { + ofono_init_default_modem(); + hfp = TRUE; + } + } + + return hfp; +} + +static void discovery_result_cb(void *closure, int status, struct json_object *result) +{ + enum json_type type; + struct json_object *devs, *dev; + int i; + + json_object_object_foreach(result, key, val) { + type = json_object_get_type(val); + switch (type) { + case json_type_array: + json_object_object_get_ex(result, key, &devs); + for (i = 0; i < json_object_array_length(devs); i++) { + dev = json_object_array_get_idx(devs, i); + if (is_hfp_dev_and_init(dev)) + break; + } + break; + case json_type_string: + case json_type_boolean: + case json_type_double: + case json_type_int: + case json_type_object: + case json_type_null: + default: + break; + } + } +} + +static void ofono_hfp_init(void) +{ + struct json_object *args, *response; + + args = json_object_new_object(); + json_object_object_add(args , "value", json_object_new_string("connection")); + afb_service_call_sync("Bluetooth-Manager", "subscribe", args, &response); + + args = json_object_new_object(); + afb_service_call("Bluetooth-Manager", "discovery_result", args, discovery_result_cb, &response); +} + static int ofono_init(void) { pthread_t tid; @@ -188,29 +270,21 @@ static int ofono_init(void) incoming_call_event = afb_daemon_make_event("incomingCall"); terminated_call_event = afb_daemon_make_event("terminatedCall"); + ret = afb_daemon_require_api("Bluetooth-Manager", 1); + if (ret) { + AFB_ERROR("unable to initialize bluetooth binding"); + return -1; + } + /* Start the main loop thread */ pthread_create(&tid, NULL, main_loop_thread, NULL); ret = ofono_manager_init(); if (ret == 0) { - const gchar *modem_path = ofono_manager_get_default_modem_path(); - if (modem_path) { - AFB_DEBUG("modem_path: %s\n", modem_path); - vcm = ofono_voicecallmanager_init(modem_path, - incoming_call_cb, - dialing_call_cb, - terminated_call_cb); - if (!vcm) { - AFB_ERROR("failed to initialize voice call manager\n"); - ret = -1; - } - } else { - AFB_ERROR("default modem not set\n"); - ret = -1; - } + ofono_manager_invalidate_default_modem(); + ofono_hfp_init(); } else { - AFB_ERROR("failed to initialize ofono manager: " \ - "HFP device not connected or Bluetooth disabled\n"); + AFB_ERROR("failed to initialize ofono manager"); } return ret; @@ -257,9 +331,41 @@ static int init() return ofono_init(); } +static void process_connection_event(struct json_object *object) +{ + struct json_object *args, *response, *status_obj, *address_obj; + const char *status, *address; + + json_object_object_get_ex(object, "Status", &status_obj); + status = json_object_get_string(status_obj); + + if (!g_strcmp0(status, "connected")) { + args = json_object_new_object(); + afb_service_call("Bluetooth-Manager", "discovery_result", + args, discovery_result_cb, &response); + } else if (!g_strcmp0(status, "disconnected")) { + json_object_object_get_ex(object, "Address", &address_obj); + address = json_object_get_string(address_obj); + if (!g_strcmp0(address, ofono_manager_get_default_modem_address())) { + ofono_manager_invalidate_default_modem(); + ofono_voicecallmanager_free(vcm); + } + } else + AFB_ERROR("Unsupported connection status: %s\n", status); +} + +static void onevent(const char *event, struct json_object *object) +{ + if (!g_strcmp0(event, "Bluetooth-Manager/connection")) + process_connection_event(object); + else + AFB_ERROR("Unsupported event: %s\n", event); +} + const struct afb_binding_v2 afbBindingV2 = { .api = "telephony", .specification = NULL, .verbs = verbs, .init = init, + .onevent = onevent, }; -- cgit 1.2.3-korg