4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Sudipto Bal <sudipto.bal@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
29 #include <oal-event.h>
31 #include "bt-service-battery-monitor.h"
32 #include "bt-service-common.h"
33 #include "bt-service-event.h"
34 #include "bt-service-core-adapter.h"
36 static time_t scan_start = 0;
37 static time_t connect_start = 0;
38 static time_t app_scan_base = 0;
39 static int scan_cnt = 0;
40 static int connect_cnt = 0;
41 static gboolean is_session_started = FALSE;
43 static GSList *scan_app_list = NULL;
48 } bt_service_oal_event_data_t;
50 _bt_battery_data_t *current_session_data = NULL;
52 static void __bt_bm_add_prev_time(uint32_t scan_time);
54 static void __bt_display_session_data()
56 BT_DBG("Displaying session data...");
57 BT_DBG("session_start_time = %ld", current_session_data->session_start_time);
58 BT_DBG("session_end_time = %ld", current_session_data->session_end_time);
59 BT_DBG("session_scan_time = %d", current_session_data->session_scan_time);
60 BT_DBG("session_connected_time = %d", current_session_data->session_connected_time);
63 /*After reading data, the function resets it*/
64 int _bt_bm_read_data(_bt_battery_data_t *data)
68 uint32_t idle_time = 0;
69 uint32_t energy_used = 0;
71 uint16_t scan_time_per_app = 0;
77 BT_ERR("Received NULL pointer in argument, returning...");
78 return BLUETOOTH_ERROR_NO_DATA;
81 if (_bt_get_energy_info(&tx_time, &rx_time,
82 &idle_time, &energy_used) != BLUETOOTH_ERROR_NONE) {
83 BT_ERR("Fail to get energy info");
84 return BLUETOOTH_ERROR_NOT_SUPPORT;
87 data->tx_time = tx_time;
88 data->rx_time = rx_time;
89 data->idle_time = idle_time;
91 data->session_start_time = current_session_data->session_start_time;
92 data->session_end_time = time(NULL);
93 current_session_data->session_start_time = time(NULL);
94 current_session_data->session_end_time = 0;
96 data->session_scan_time = current_session_data->session_scan_time;
98 data->session_scan_time += (uint16_t) (time(NULL) - scan_start);
99 scan_start = time(NULL);
100 base_time = app_scan_base;
101 app_scan_base = scan_start;
104 data->session_connected_time = current_session_data->session_connected_time;
106 data->session_connected_time += (uint16_t) (time(NULL) - connect_start);
107 connect_start = time(NULL);
110 scan_app_cnt = g_slist_length(scan_app_list);
112 if (scan_app_cnt > 0) {
113 scan_time_per_app = (uint32_t)(app_scan_base - base_time) / scan_app_cnt;
114 __bt_bm_add_prev_time(scan_time_per_app);
117 data->atm_list = current_session_data->atm_list;
118 if (data->atm_list == NULL) {
119 BT_DBG("No data transaction in this session");
120 return BLUETOOTH_ERROR_NONE;
123 BT_DBG("App-wise data transaction details");
124 for (GSList *l = data->atm_list; l != NULL; l = g_slist_next(l)) {
125 _bt_battery_app_data_t *t = (_bt_battery_app_data_t *)(l->data);
126 BT_DBG("%ld %ld %d %d %u", (long int)(t->uid), (long int)(t->pid), t->rx_bytes, t->tx_bytes, t->time);
129 current_session_data->atm_list = NULL;
130 return BLUETOOTH_ERROR_NONE;
133 static GSList* is_app_present(GSList *start, uid_t uid, pid_t pid)
136 _bt_battery_app_data_t *t;
137 BT_INFO("Checking Memory location %p", start);
138 for (l=start; l != NULL; l = g_slist_next(l)) {
139 t = (_bt_battery_app_data_t *)(l->data);
140 if (t->uid == uid && t->pid == pid) {
141 BT_INFO("App details already exist");
148 void _bt_bm_add_transaction_details(uid_t uid, pid_t pid, int value, data_transaction_type_e type)
150 if (current_session_data == NULL) {
151 BT_ERR("Session in progress but data structure is not initialized"); //error handling
154 GSList *t = is_app_present(current_session_data->atm_list, uid, pid);
155 _bt_battery_app_data_t *app_data = NULL;
158 BT_INFO("Match not found, adding new node...");
159 app_data = g_malloc0(sizeof(_bt_battery_app_data_t));
163 app_data->rx_bytes = value;
164 else if (type == TX_DATA)
165 app_data->tx_bytes = value;
167 app_data->time = value;
168 current_session_data->atm_list = g_slist_append(current_session_data->atm_list, app_data);
171 BT_INFO("Match found, updating existing node...");
172 app_data = (_bt_battery_app_data_t *)(t->data);
174 app_data->rx_bytes += value;
175 else if (type == TX_DATA)
176 app_data->tx_bytes += value;
178 app_data->time += value;
182 void _bt_start_session_time()
184 if (is_session_started == FALSE) {
185 BT_DBG("Bt session starting...");
186 is_session_started = TRUE;
187 current_session_data = g_malloc0(sizeof(_bt_battery_data_t));
188 current_session_data->session_start_time = time(NULL);
189 current_session_data->session_end_time = 0;
190 current_session_data->session_connected_time = 0;
191 current_session_data->session_scan_time = 0;
192 current_session_data->atm_list = NULL;
194 if (current_session_data == NULL)
195 BT_ERR("Session in progress but data structure is not initialized"); //error handling
197 BT_DBG("Bt session already in progress... Returning");
201 void _bt_stop_session_time()
203 if (is_session_started == FALSE) {
204 BT_DBG("BT session not in progress... Returning"); //error handling
207 BT_DBG("Bt session ending...");
208 is_session_started = FALSE;
209 current_session_data->session_end_time = time(NULL);
210 __bt_display_session_data();
213 /* 1 app can operate the regacy and ble scan at the same time */
214 static GSList* __is_scan_app_present(GSList *start, bt_bm_scan_type_e type, uid_t uid, pid_t pid)
217 bt_bm_scan_info_t *t;
219 for (l = start; l != NULL; l = g_slist_next(l)) {
220 t = (bt_bm_scan_info_t *)(l->data);
222 /* Find the regacy scan app for Inquiry stop */
223 if (type == SCAN_REGACY && t->type != SCAN_LE) {
224 BT_INFO("app already exist");
228 if (t->uid == uid && t->pid == pid) {
229 BT_INFO("app already exist");
236 static void __bt_bm_add_prev_time(uint32_t scan_time)
239 bt_bm_scan_info_t *t;
241 for (l = scan_app_list; l != NULL; l = g_slist_next(l)) {
242 t = (bt_bm_scan_info_t *)(l->data);
243 _bt_bm_add_transaction_details(t->uid, t->pid, scan_time, TIME_DATA);
247 /* 1 regacy scan is only allowed in the platform
248 * BLE scan is allowed for many apps
250 /* When a app is added, we should add and reset the time. */
251 void _bt_bm_add_scan_app(bt_bm_scan_type_e type, uid_t uid, pid_t pid)
253 bt_bm_scan_info_t *scan_info = NULL;
254 GSList *app_list = NULL;
256 time_t base_time = 0;
257 uint16_t scan_time_per_app = 0;
259 BT_DBG("Scan type: %d", type);
261 /* Update the base time */
262 base_time = app_scan_base;
263 app_scan_base = time(NULL);
266 app_cnt = g_slist_length(scan_app_list);
267 app_list = __is_scan_app_present(scan_app_list, SCAN_BOTH, uid, pid);
271 /* app try to scan both Regacy and LE */
272 scan_info = (bt_bm_scan_info_t *)(app_list->data);
274 if (scan_info == NULL) {
275 BT_ERR("Can't get the scan info");
279 BT_DBG("Previous type: %d", scan_info->type);
281 if (scan_info->type == type) {
282 BT_ERR("Same scan type is doing");
286 scan_info->type = SCAN_BOTH;
288 scan_info = g_malloc0(sizeof(bt_bm_scan_info_t));
289 scan_info->uid = uid;
290 scan_info->pid = pid;
291 scan_info->type = type;
293 if (app_cnt > 0 && base_time != 0) {
294 /* Update the base time */
295 base_time = app_scan_base;
296 app_scan_base = time(NULL);
298 scan_time_per_app = (uint32_t)(app_scan_base - base_time) / app_cnt;
299 __bt_bm_add_prev_time(scan_time_per_app);
302 scan_app_list = g_slist_append(scan_app_list, scan_info);
306 /* When a app is removed, we should add and reset the time. */
307 void _bt_bm_remove_scan_app(bt_bm_scan_type_e type, uid_t uid, pid_t pid)
309 bt_bm_scan_info_t *scan_info = NULL;
310 GSList *app_list = NULL;
312 time_t base_time = 0;
313 uint16_t scan_time_per_app = 0;
315 BT_DBG("Scan type: %d", type);
317 if (scan_app_list == NULL) {
318 BT_ERR("No scan app in list");
322 app_cnt = g_slist_length(scan_app_list);
325 BT_ERR("No scan app in list");
329 app_list = __is_scan_app_present(scan_app_list, type, uid, pid);
332 scan_info = (bt_bm_scan_info_t *)(app_list->data);
334 if (scan_info->type == SCAN_BOTH) {
335 scan_info->type = (scan_info->type == SCAN_REGACY) ? SCAN_LE : SCAN_REGACY;
339 /* Update the base time */
340 base_time = app_scan_base;
341 app_scan_base = time(NULL);
343 if (base_time != 0) {
344 scan_time_per_app = (uint32_t)(app_scan_base - base_time) / app_cnt;
345 __bt_bm_add_prev_time(scan_time_per_app);
348 scan_app_list = g_slist_remove(scan_app_list, scan_info);
354 void _bt_start_scan_time()
356 if (current_session_data != NULL) {
358 BT_DBG("Starting scan time");
359 scan_start = time(NULL);
360 app_scan_base = scan_start;
364 BT_ERR("Data structure uninitialized"); //error handling
368 void _bt_stop_scan_time()
370 if (scan_cnt == 0 || current_session_data == NULL)
371 BT_ERR("Error encountered, returning..."); //error handling
375 time_t temp = time(NULL);
376 current_session_data->session_scan_time += (uint16_t) (temp - scan_start);
378 app_scan_base = scan_start;
383 void _bt_start_connect_time()
385 if (current_session_data != NULL) {
386 if (connect_cnt == 0) {
387 BT_DBG("Starting connect time");
388 connect_start = time(NULL);
393 BT_ERR("Data structure uninitialized"); //error handling
397 void _bt_stop_connect_time()
399 if(connect_cnt == 0 || current_session_data == NULL) {
400 BT_ERR("Error encountered, returning..."); //error handling
404 if(connect_cnt == 0) {
405 time_t temp = time(NULL);
406 current_session_data->session_connected_time += (uint16_t) (temp - connect_start);
411 static void _bt_notify_battery_data(void)
414 _bt_battery_data_t *data = NULL;
417 data = g_new0(_bt_battery_data_t, 1);
418 result = _bt_bm_read_data(data);
419 GVariant *out_var = NULL, *param = NULL;
422 if (result != BLUETOOTH_ERROR_NONE) {
423 BT_ERR("Battery data not collected");
426 bt_battery_dbus_data_t dbus_data;
427 memset(&dbus_data, 0, sizeof(bt_battery_dbus_data_t));
428 dbus_data.session_start_time = data->session_start_time;
429 dbus_data.session_end_time = data->session_end_time;
430 dbus_data.session_scan_time = data->session_scan_time;
431 dbus_data.session_connected_time = data->session_connected_time;
432 dbus_data.tx_time = data->tx_time;
433 dbus_data.rx_time = data->rx_time;
434 dbus_data.idle_time = data->idle_time;
436 /*Populating app data*/
438 for (GSList *l = data->atm_list; l != NULL; l = g_slist_next(l)) {
439 bt_battery_app_data *t = (bt_battery_app_data *)(l->data);
440 memcpy(&dbus_data.app_data[n], t, sizeof(bt_battery_app_data));
443 dbus_data.num_app = n;
445 info = g_array_new(FALSE, FALSE, sizeof(gchar));
446 g_array_append_vals(info, &dbus_data, sizeof(bt_battery_dbus_data_t));
448 out_var = g_variant_new_from_data((const GVariantType *)"ay",
449 info->data, info->len,
452 param = g_variant_new("(iv)", result, out_var);
453 _bt_send_event(BT_ADAPTER_EVENT,
454 BLUETOOTH_EVENT_DISABLED_BATTERY_DATA,
457 g_slist_free(data->atm_list);
459 g_array_free(info, TRUE);
463 void _bt_bm_event_handler(gpointer data)
465 bt_service_oal_event_data_t *oal_event = data;
466 int event_type = oal_event->type;
469 case OAL_EVENT_ADAPTER_ENABLED:
470 BT_DBG("Handling Adapter Enabled");
471 _bt_start_session_time();
473 case OAL_EVENT_ADAPTER_DISABLED:
474 BT_DBG("Handling Adapter Disabled");
475 _bt_stop_session_time();
476 _bt_notify_battery_data();
478 case OAL_EVENT_ADAPTER_INQUIRY_STARTED:
479 case OAL_EVENT_BLE_DISCOVERY_STARTED:
480 BT_DBG("Handling Adapter Discovery Start");
481 _bt_start_scan_time();
483 case OAL_EVENT_ADAPTER_INQUIRY_FINISHED:
484 /* Remove the regacy scan app */
485 _bt_bm_remove_scan_app(SCAN_REGACY, 0, 0);
487 _bt_stop_scan_time();
489 case OAL_EVENT_BLE_DISCOVERY_STOPPED:
490 BT_DBG("Handling Adapter Discovery Stop");
491 _bt_stop_scan_time();
493 case OAL_EVENT_SOCKET_OUTGOING_CONNECTED:
494 case OAL_EVENT_GATTC_CONNECTION_COMPLETED:
495 BT_DBG("Handling Connection Start");
496 _bt_start_connect_time();
498 case OAL_EVENT_SOCKET_DISCONNECTED:
499 case OAL_EVENT_GATTC_DISCONNECTION_COMPLETED:
500 BT_DBG("Handling Connection Stop");
501 _bt_stop_connect_time();
504 BT_DBG("The event is not currently being handled");