59d93cd345bdb1c917d2546d279a56a8347b8f53
[platform/core/connectivity/bluetooth-frwk.git] / bt-service-adaptation / services / bt-service-battery-monitor.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Sudipto Bal <sudipto.bal@samsung.com>
7  *
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
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #include <glib.h>
23 #include <gio/gio.h>
24 #include <string.h>
25 #include <dlog.h>
26 #include <time.h>
27
28
29 #include <oal-event.h>
30
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"
35
36 static time_t scan_start = 0;
37 static time_t connect_start = 0;
38 static int scan_cnt = 0;
39 static int connect_cnt = 0;
40 static gboolean is_session_started = FALSE;
41
42 typedef struct {
43         int type;
44         void *data;
45 } bt_service_oal_event_data_t;
46
47 _bt_battery_data_t *current_session_data = NULL;
48
49 static void __bt_display_session_data()
50 {
51         BT_DBG("Displaying session data...");
52         BT_DBG("session_start_time = %ld", current_session_data->session_start_time);
53         BT_DBG("session_end_time = %ld", current_session_data->session_end_time);
54         BT_DBG("session_scan_time = %d", current_session_data->session_scan_time);
55         BT_DBG("session_connected_time = %d", current_session_data->session_connected_time);
56 }
57
58 /*After reading data, the function resets it*/
59 int _bt_bm_read_data(_bt_battery_data_t *data)
60 {
61         uint32_t tx_time = 0;
62         uint32_t rx_time = 0;
63         uint32_t idle_time = 0;
64         uint32_t energy_used = 0;
65
66         BT_DBG("");
67
68         if (data == NULL) {
69                 BT_ERR("Received NULL pointer in argument, returning...");
70                 return BLUETOOTH_ERROR_NO_DATA;
71         }
72
73         if (_bt_get_energy_info(&tx_time, &rx_time,
74                                 &idle_time, &energy_used) != BLUETOOTH_ERROR_NONE) {
75                 BT_ERR("Fail to get energy info");
76                 return BLUETOOTH_ERROR_NOT_SUPPORT;
77         }
78
79         data->tx_time = tx_time;
80         data->rx_time = rx_time;
81         data->idle_time = idle_time;
82
83         data->session_start_time = current_session_data->session_start_time;
84         data->session_end_time = time(NULL);
85         current_session_data->session_start_time = time(NULL);
86         current_session_data->session_end_time = 0;
87
88         data->session_scan_time = current_session_data->session_scan_time;
89         if (scan_cnt) {
90                 data->session_scan_time += (uint16_t) (time(NULL) - scan_start);
91                 scan_start = time(NULL);
92         }
93
94         data->session_connected_time = current_session_data->session_connected_time;
95         if (connect_cnt) {
96                 data->session_connected_time += (uint16_t) (time(NULL) - connect_start);
97                 connect_start = time(NULL);
98         }
99
100         data->atm_list = current_session_data->atm_list;
101         if (data->atm_list == NULL) {
102                 BT_DBG("No data transaction in this session");
103                 return BLUETOOTH_ERROR_NONE;
104         }
105
106         BT_DBG("App-wise data transaction details");
107         for (GSList *l = data->atm_list; l != NULL; l = g_slist_next(l)) {
108                 _bt_battery_app_data_t *t = (_bt_battery_app_data_t *)(l->data);
109                 BT_DBG("%ld %ld %d %d %u", (long int)(t->uid), (long int)(t->pid), t->rx_bytes, t->tx_bytes, t->time);
110         }
111
112         current_session_data->atm_list = NULL;
113         return BLUETOOTH_ERROR_NONE;
114 }
115
116 static GSList* is_app_present(GSList *start, uid_t uid, pid_t pid)
117 {
118         GSList *l = NULL;
119         _bt_battery_app_data_t *t;
120         BT_INFO("Checking Memory location %p", start);
121         for (l=start; l != NULL; l = g_slist_next(l)) {
122                 t = (_bt_battery_app_data_t *)(l->data);
123                 if (t->uid == uid && t->pid == pid) {
124                         BT_INFO("App details already exist");
125                         return l;
126                 }
127         }
128         return NULL;
129 }
130
131 void _bt_bm_add_transaction_details(uid_t uid, pid_t pid, int size, data_transaction_type_e type)
132 {
133         if (current_session_data == NULL) {
134                 BT_ERR("Session in progress but data structure is not initialized"); //error handling
135                 return;
136         }
137         GSList *t = is_app_present(current_session_data->atm_list, uid, pid);
138         _bt_battery_app_data_t *app_data = NULL;
139
140         if (t == NULL) {
141                 BT_INFO("Match not found, adding new node...");
142                 app_data = g_malloc0(sizeof(_bt_battery_app_data_t));
143                 app_data->uid = uid;
144                 app_data->pid = pid;
145                 if (type == RX_DATA)
146                         app_data->rx_bytes = size;
147                 else
148                         app_data->tx_bytes = size;
149                 current_session_data->atm_list = g_slist_append(current_session_data->atm_list, app_data);
150         }
151         else {
152                 BT_INFO("Match found, updating existing node...");
153                 app_data = (_bt_battery_app_data_t *)(t->data);
154                 if (type == RX_DATA)
155                         app_data->rx_bytes += size;
156                 else
157                         app_data->tx_bytes += size;
158         }
159 }
160
161 void _bt_start_session_time()
162 {
163         if (is_session_started == FALSE) {
164                 BT_DBG("Bt session starting...");
165                 is_session_started = TRUE;
166                 current_session_data = g_malloc0(sizeof(_bt_battery_data_t));
167                 current_session_data->session_start_time = time(NULL);
168                 current_session_data->session_end_time = 0;
169                 current_session_data->session_connected_time = 0;
170                 current_session_data->session_scan_time = 0;
171                 current_session_data->atm_list = NULL;
172         } else {
173                 if (current_session_data == NULL)
174                         BT_ERR("Session in progress but data structure is not initialized"); //error handling
175                 else
176                         BT_DBG("Bt session already in progress... Returning");
177         }
178 }
179
180 void _bt_stop_session_time()
181 {
182         if (is_session_started == FALSE) {
183                 BT_DBG("BT session not in progress... Returning"); //error handling
184                 return;
185         }
186         BT_DBG("Bt session ending...");
187         is_session_started = FALSE;
188         current_session_data->session_end_time = time(NULL);
189         __bt_display_session_data();
190 }
191
192 void _bt_start_scan_time()
193 {
194         if (current_session_data != NULL) {
195                 if (scan_cnt == 0) {
196                         BT_DBG("Starting scan time");
197                         scan_start = time(NULL);
198                 }
199                 scan_cnt++;
200         } else {
201                 BT_ERR("Data structure uninitialized"); //error handling
202         }
203 }
204
205 void _bt_stop_scan_time()
206 {
207         if (scan_cnt == 0 || current_session_data == NULL)
208                 BT_ERR("Error encountered, returning..."); //error handling
209         else {
210                 scan_cnt--;
211                 if(scan_cnt == 0) {
212                         time_t temp = time(NULL);
213                         current_session_data->session_scan_time += (uint16_t) (temp - scan_start);
214                 }
215         }
216 }
217
218 void _bt_start_connect_time()
219 {
220         if (current_session_data != NULL) {
221                 if (connect_cnt == 0) {
222                         BT_DBG("Starting connect time");
223                         connect_start = time(NULL);
224                 }
225                 connect_cnt++;
226         }
227         else {
228                 BT_ERR("Data structure uninitialized"); //error handling
229         }
230 }
231
232 void _bt_stop_connect_time()
233 {
234         if(connect_cnt == 0 || current_session_data == NULL) {
235                 BT_ERR("Error encountered, returning..."); //error handling
236         }
237         else {
238                 connect_cnt--;
239                 if(connect_cnt == 0) {
240                         time_t temp = time(NULL);
241                         current_session_data->session_connected_time += (uint16_t) (temp - connect_start);
242                 }
243         }
244 }
245
246 static void _bt_notify_battery_data(void)
247 {
248         BT_INFO("+");
249         _bt_battery_data_t *data = NULL;
250         int result;
251
252         data = g_new0(_bt_battery_data_t, 1);
253         result = _bt_bm_read_data(data);
254         GVariant *out_var = NULL, *param = NULL;
255         GArray *info = NULL;
256
257         if (result != BLUETOOTH_ERROR_NONE) {
258                 BT_ERR("Battery data not collected");
259         }
260         else {
261                 bt_battery_dbus_data_t dbus_data;
262                 memset(&dbus_data, 0, sizeof(bt_battery_dbus_data_t));
263                 dbus_data.session_start_time = data->session_start_time;
264                 dbus_data.session_end_time = data->session_end_time;
265                 dbus_data.session_scan_time = data->session_scan_time;
266                 dbus_data.session_connected_time = data->session_connected_time;
267                 dbus_data.tx_time = data->tx_time;
268                 dbus_data.rx_time = data->rx_time;
269                 dbus_data.idle_time = data->idle_time;
270
271                 /*Populating app data*/
272                 int n = 0;
273                 for (GSList *l = data->atm_list; l != NULL; l = g_slist_next(l)) {
274                         bt_battery_app_data *t = (bt_battery_app_data *)(l->data);
275                         memcpy(&dbus_data.app_data[n], t, sizeof(bt_battery_app_data));
276                         n++;
277                 }
278                 dbus_data.num_app = n;
279
280                 info = g_array_new(FALSE, FALSE, sizeof(gchar));
281                 g_array_append_vals(info, &dbus_data, sizeof(bt_battery_dbus_data_t));
282
283                 out_var = g_variant_new_from_data((const GVariantType *)"ay",
284                                 info->data, info->len,
285                                 TRUE, NULL, NULL);
286         }
287         param = g_variant_new("(iv)", result, out_var);
288         _bt_send_event(BT_ADAPTER_EVENT,
289                 BLUETOOTH_EVENT_DISABLED_BATTERY_DATA,
290                 param);
291
292         g_slist_free(data->atm_list);
293         g_free(data);
294         g_array_free(info, TRUE);
295         BT_INFO("-");
296 }
297
298 void _bt_bm_event_handler(gpointer data)
299 {
300         bt_service_oal_event_data_t *oal_event = data;
301         int event_type = oal_event->type;
302
303         switch(event_type) {
304         case OAL_EVENT_ADAPTER_ENABLED:
305                 BT_DBG("Handling Adapter Enabled");
306                 _bt_start_session_time();
307                 break;
308         case OAL_EVENT_ADAPTER_DISABLED:
309                 BT_DBG("Handling Adapter Disabled");
310                 _bt_stop_session_time();
311                 _bt_notify_battery_data();
312                 break;
313         case OAL_EVENT_ADAPTER_INQUIRY_STARTED:
314         case OAL_EVENT_BLE_DISCOVERY_STARTED:
315                 BT_DBG("Handling Adapter Discovery Start");
316                 _bt_start_scan_time();
317                 break;
318         case OAL_EVENT_ADAPTER_INQUIRY_FINISHED:
319         case OAL_EVENT_BLE_DISCOVERY_STOPPED:
320                 BT_DBG("Handling Adapter Discovery Stop");
321                 _bt_stop_scan_time();
322                 break;
323         case OAL_EVENT_SOCKET_OUTGOING_CONNECTED:
324         case OAL_EVENT_GATTC_CONNECTION_COMPLETED:
325                 BT_DBG("Handling Connection Start");
326                 _bt_start_connect_time();
327                 break;
328         case OAL_EVENT_SOCKET_DISCONNECTED:
329         case OAL_EVENT_GATTC_DISCONNECTION_COMPLETED:
330                 BT_DBG("Handling Connection Stop");
331                 _bt_stop_connect_time();
332                 break;
333         default:
334                 BT_DBG("The event is not currently being handled");
335         }
336 }