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