1 /* 2 * Copyright 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 static std::mutex set_lock; 31 32 typedef struct uid_set_node_t { 33 struct uid_set_node_t* next; 34 bt_uid_traffic_t data; 35 } uid_set_node_t; 36 37 typedef struct uid_set_t { 38 uid_set_node_t* head; 39 } uid_set_t; 40 41 uid_set_t* uid_set_create(void) { 42 uid_set_t* set = (uid_set_t*)osi_calloc(sizeof(uid_set_t)); 43 return set; 44 } 45 46 void uid_set_destroy(uid_set_t* set) { 47 std::unique_lock<std::mutex> guard(set_lock); 48 uid_set_node_t* node = set->head; 49 while (node) { 50 uid_set_node_t* temp = node; 51 node = node->next; 52 osi_free(temp); 53 } 54 set->head = NULL; 55 osi_free(set); 56 } 57 58 // Lock in uid_set_t must be held. 59 static uid_set_node_t* uid_set_find_or_create_node(uid_set_t* set, 60 int32_t app_uid) { 61 uid_set_node_t* node = set->head; 62 while (node && node->data.app_uid != app_uid) { 63 node = node->next; 64 } 65 66 if (!node) { 67 node = (uid_set_node_t*)osi_calloc(sizeof(uid_set_node_t)); 68 node->data.app_uid = app_uid; 69 node->next = set->head; 70 set->head = node; 71 } 72 return node; 73 } 74 75 void uid_set_add_tx(uid_set_t* set, int32_t app_uid, uint64_t bytes) { 76 if (app_uid == -1 || bytes == 0) return; 77 78 std::unique_lock<std::mutex> guard(set_lock); 79 uid_set_node_t* node = uid_set_find_or_create_node(set, app_uid); 80 node->data.tx_bytes += bytes; 81 } 82 83 void uid_set_add_rx(uid_set_t* set, int32_t app_uid, uint64_t bytes) { 84 if (app_uid == -1 || bytes == 0) return; 85 86 std::unique_lock<std::mutex> guard(set_lock); 87 uid_set_node_t* node = uid_set_find_or_create_node(set, app_uid); 88 node->data.rx_bytes += bytes; 89 } 90 91 bt_uid_traffic_t* uid_set_read_and_clear(uid_set_t* set) { 92 std::unique_lock<std::mutex> guard(set_lock); 93 94 // Find the length 95 size_t len = 0; 96 uid_set_node_t* node = set->head; 97 while (node) { 98 len++; 99 node = node->next; 100 } 101 102 // Allocate an array of elements + 1, to signify the end with app_uid set to 103 // -1. 104 bt_uid_traffic_t* result = 105 (bt_uid_traffic_t*)osi_calloc(sizeof(bt_uid_traffic_t) * (len + 1)); 106 107 bt_uid_traffic_t* data = result; 108 node = set->head; 109 while (node) { 110 // Copy the data. 111 *data = node->data; 112 data++; 113 114 // Clear the counters. 115 node->data.rx_bytes = 0; 116 node->data.tx_bytes = 0; 117 node = node->next; 118 } 119 120 // Mark the last entry 121 data->app_uid = -1; 122 123 return result; 124 } 125