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