10620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski/*
20620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski * Copyright (C) 2016 The Android Open Source Project
30620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski *
40620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
50620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski * you may not use this file except in compliance with the License.
60620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski * You may obtain a copy of the License at
70620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski *
80620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
90620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski *
100620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski * Unless required by applicable law or agreed to in writing, software
110620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
120620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski * See the License for the specific language governing permissions and
140620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski * limitations under the License.
150620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski */
160620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski
17ee96a3c60fca590d38025925c072d264e06493c4Myles Watson/*******************************************************************************
180620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski *
19a5764686f719d8d779d8a5ff8cc64010b7893e36Marie Janssen *  Filename:      btif_uid.cc
200620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski *
210620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski *  Description:   Contains data structures and functions for keeping track of
220620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski *                 socket usage per app UID.
230620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski *
24ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
25a5764686f719d8d779d8a5ff8cc64010b7893e36Marie Janssen#include <mutex>
262f0c1fff33eda347cb45d00b005e805c39474dceMark Salyzyn
270620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski#include "bt_common.h"
280620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski#include "btif_uid.h"
290620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski
300620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinskitypedef struct uid_set_node_t {
316bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  struct uid_set_node_t* next;
326bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  bt_uid_traffic_t data;
330620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski} uid_set_node_t;
340620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski
350620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinskitypedef struct uid_set_t {
366bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  std::mutex lock;
376bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uid_set_node_t* head;
380620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski} uid_set_t;
390620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski
400620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinskiuid_set_t* uid_set_create(void) {
416bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uid_set_t* set = (uid_set_t*)osi_calloc(sizeof(uid_set_t));
426bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  return set;
430620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski}
440620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski
450620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinskivoid uid_set_destroy(uid_set_t* set) {
466bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  std::unique_lock<std::mutex> lock(set->lock);
476bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uid_set_node_t* node = set->head;
486bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  while (node) {
496bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    uid_set_node_t* temp = node;
506bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    node = node->next;
516bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    osi_free(temp);
526bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
536bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  set->head = NULL;
546bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  osi_free(set);
550620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski}
560620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski
570620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski// Lock in uid_set_t must be held.
586bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic uid_set_node_t* uid_set_find_or_create_node(uid_set_t* set,
596bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                                                   int32_t app_uid) {
606bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uid_set_node_t* node = set->head;
616bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  while (node && node->data.app_uid != app_uid) {
626bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    node = node->next;
636bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
646bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
656bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (!node) {
666bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    node = (uid_set_node_t*)osi_calloc(sizeof(uid_set_node_t));
676bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    node->data.app_uid = app_uid;
686bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    node->next = set->head;
696bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    set->head = node;
706bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
716bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  return node;
720620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski}
730620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski
740620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinskivoid uid_set_add_tx(uid_set_t* set, int32_t app_uid, uint64_t bytes) {
756bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (app_uid == -1 || bytes == 0) return;
760620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski
776bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  std::unique_lock<std::mutex> lock(set->lock);
786bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uid_set_node_t* node = uid_set_find_or_create_node(set, app_uid);
796bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  node->data.tx_bytes += bytes;
800620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski}
810620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski
820620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinskivoid uid_set_add_rx(uid_set_t* set, int32_t app_uid, uint64_t bytes) {
836bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (app_uid == -1 || bytes == 0) return;
840620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski
856bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  std::unique_lock<std::mutex> lock(set->lock);
866bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uid_set_node_t* node = uid_set_find_or_create_node(set, app_uid);
876bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  node->data.rx_bytes += bytes;
880620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski}
890620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski
900620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinskibt_uid_traffic_t* uid_set_read_and_clear(uid_set_t* set) {
916bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  std::unique_lock<std::mutex> lock(set->lock);
926bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
936bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  // Find the length
946bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  size_t len = 0;
956bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uid_set_node_t* node = set->head;
966bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  while (node) {
976bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    len++;
986bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    node = node->next;
996bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
1006bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
1016bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  // Allocate an array of elements + 1, to signify the end with app_uid set to
1026bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  // -1.
1036bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  bt_uid_traffic_t* result =
1046bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      (bt_uid_traffic_t*)osi_calloc(sizeof(bt_uid_traffic_t) * (len + 1));
1056bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
1066bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  bt_uid_traffic_t* data = result;
1076bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  node = set->head;
1086bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  while (node) {
1096bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    // Copy the data.
1106bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    *data = node->data;
1116bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    data++;
1126bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
1136bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    // Clear the counters.
1146bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    node->data.rx_bytes = 0;
1156bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    node->data.tx_bytes = 0;
1166bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    node = node->next;
1176bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
1186bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
1196bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  // Mark the last entry
1206bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  data->app_uid = -1;
1216bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
1226bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  return result;
1230620f9706d9aa06ba7f8982840eeb7ab2ad90e7aAdam Lesinski}
124