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.c 20 * 21 * Description: Contains data structures and functions for keeping track of 22 * socket usage per app UID. 23 * 24 ***********************************************************************************/ 25 #define LOG_TAG "bt_uid_set" 26 #include "bt_common.h" 27 #include "btif_uid.h" 28 29 #include <log/log.h> 30 #include <pthread.h> 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 pthread_mutex_t lock; 39 uid_set_node_t* head; 40 } uid_set_t; 41 42 uid_set_t* uid_set_create(void) { 43 uid_set_t* set = osi_calloc(sizeof(uid_set_t)); 44 pthread_mutex_init(&set->lock, NULL); 45 return set; 46 } 47 48 void uid_set_destroy(uid_set_t* set) { 49 pthread_mutex_lock(&set->lock); 50 uid_set_node_t* node = set->head; 51 while (node) { 52 uid_set_node_t* temp = node; 53 node = node->next; 54 osi_free(temp); 55 } 56 set->head = NULL; 57 pthread_mutex_unlock(&set->lock); 58 pthread_mutex_destroy(&set->lock); 59 osi_free(set); 60 } 61 62 // Lock in uid_set_t must be held. 63 static uid_set_node_t* uid_set_find_or_create_node(uid_set_t* set, int32_t app_uid) { 64 uid_set_node_t* node = set->head; 65 while (node && node->data.app_uid != app_uid) { 66 node = node->next; 67 } 68 69 if (!node) { 70 node = osi_calloc(sizeof(uid_set_node_t)); 71 node->data.app_uid = app_uid; 72 node->next = set->head; 73 set->head = node; 74 } 75 return node; 76 } 77 78 void uid_set_add_tx(uid_set_t* set, int32_t app_uid, uint64_t bytes) { 79 if (app_uid == -1 || bytes == 0) { 80 return; 81 } 82 83 pthread_mutex_lock(&set->lock); 84 uid_set_node_t* node = uid_set_find_or_create_node(set, app_uid); 85 node->data.tx_bytes += bytes; 86 pthread_mutex_unlock(&set->lock); 87 } 88 89 void uid_set_add_rx(uid_set_t* set, int32_t app_uid, uint64_t bytes) { 90 if (app_uid == -1 || bytes == 0) { 91 return; 92 } 93 94 pthread_mutex_lock(&set->lock); 95 uid_set_node_t* node = uid_set_find_or_create_node(set, app_uid); 96 node->data.rx_bytes += bytes; 97 pthread_mutex_unlock(&set->lock); 98 } 99 100 bt_uid_traffic_t* uid_set_read_and_clear(uid_set_t* set) { 101 pthread_mutex_lock(&set->lock); 102 103 // Find the length 104 size_t len = 0; 105 uid_set_node_t* node = set->head; 106 while (node) { 107 len++; 108 node = node->next; 109 } 110 111 // Allocate an array of elements + 1, to signify the end with app_uid set to -1. 112 bt_uid_traffic_t* result = osi_calloc(sizeof(bt_uid_traffic_t) * (len + 1)); 113 114 bt_uid_traffic_t* data = result; 115 node = set->head; 116 while (node) { 117 // Copy the data. 118 *data = node->data; 119 data++; 120 121 // Clear the counters. 122 node->data.rx_bytes = 0; 123 node->data.tx_bytes = 0; 124 node = node->next; 125 } 126 127 // Mark the last entry 128 data->app_uid = -1; 129 130 pthread_mutex_unlock(&set->lock); 131 132 return result; 133 } 134