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