Home | History | Annotate | Download | only in src
      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