• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*******************************************************************************
18  *
19  *  Filename:      btif_uid.cc
20  *
21  *  Description:   Contains data structures and functions for keeping track of
22  *                 socket usage per app UID.
23  *
24  ******************************************************************************/
25 #include <mutex>
26 
27 #include "bt_common.h"
28 #include "btif_uid.h"
29 
30 typedef struct uid_set_node_t {
31   struct uid_set_node_t* next;
32   bt_uid_traffic_t data;
33 } uid_set_node_t;
34 
35 typedef struct uid_set_t {
36   std::mutex lock;
37   uid_set_node_t* head;
38 } uid_set_t;
39 
uid_set_create(void)40 uid_set_t* uid_set_create(void) {
41   uid_set_t* set = (uid_set_t*)osi_calloc(sizeof(uid_set_t));
42   return set;
43 }
44 
uid_set_destroy(uid_set_t * set)45 void uid_set_destroy(uid_set_t* set) {
46   std::unique_lock<std::mutex> lock(set->lock);
47   uid_set_node_t* node = set->head;
48   while (node) {
49     uid_set_node_t* temp = node;
50     node = node->next;
51     osi_free(temp);
52   }
53   set->head = NULL;
54   osi_free(set);
55 }
56 
57 // Lock in uid_set_t must be held.
uid_set_find_or_create_node(uid_set_t * set,int32_t app_uid)58 static uid_set_node_t* uid_set_find_or_create_node(uid_set_t* set,
59                                                    int32_t app_uid) {
60   uid_set_node_t* node = set->head;
61   while (node && node->data.app_uid != app_uid) {
62     node = node->next;
63   }
64 
65   if (!node) {
66     node = (uid_set_node_t*)osi_calloc(sizeof(uid_set_node_t));
67     node->data.app_uid = app_uid;
68     node->next = set->head;
69     set->head = node;
70   }
71   return node;
72 }
73 
uid_set_add_tx(uid_set_t * set,int32_t app_uid,uint64_t bytes)74 void uid_set_add_tx(uid_set_t* set, int32_t app_uid, uint64_t bytes) {
75   if (app_uid == -1 || bytes == 0) return;
76 
77   std::unique_lock<std::mutex> lock(set->lock);
78   uid_set_node_t* node = uid_set_find_or_create_node(set, app_uid);
79   node->data.tx_bytes += bytes;
80 }
81 
uid_set_add_rx(uid_set_t * set,int32_t app_uid,uint64_t bytes)82 void uid_set_add_rx(uid_set_t* set, int32_t app_uid, uint64_t bytes) {
83   if (app_uid == -1 || bytes == 0) return;
84 
85   std::unique_lock<std::mutex> lock(set->lock);
86   uid_set_node_t* node = uid_set_find_or_create_node(set, app_uid);
87   node->data.rx_bytes += bytes;
88 }
89 
uid_set_read_and_clear(uid_set_t * set)90 bt_uid_traffic_t* uid_set_read_and_clear(uid_set_t* set) {
91   std::unique_lock<std::mutex> lock(set->lock);
92 
93   // Find the length
94   size_t len = 0;
95   uid_set_node_t* node = set->head;
96   while (node) {
97     len++;
98     node = node->next;
99   }
100 
101   // Allocate an array of elements + 1, to signify the end with app_uid set to
102   // -1.
103   bt_uid_traffic_t* result =
104       (bt_uid_traffic_t*)osi_calloc(sizeof(bt_uid_traffic_t) * (len + 1));
105 
106   bt_uid_traffic_t* data = result;
107   node = set->head;
108   while (node) {
109     // Copy the data.
110     *data = node->data;
111     data++;
112 
113     // Clear the counters.
114     node->data.rx_bytes = 0;
115     node->data.tx_bytes = 0;
116     node = node->next;
117   }
118 
119   // Mark the last entry
120   data->app_uid = -1;
121 
122   return result;
123 }
124