"src/btif_sock_thread.c",
"src/btif_sock_util.c",
"src/btif_storage.c",
+ "src/btif_uid.c",
"src/btif_util.c",
"src/stack_manager.c",
]
#define BTIF_DM_H
#include "bta_api.h"
+#include "btif_uid.h"
+
/************************************************************************************
** Functions
********************************************************************************/
+void btif_dm_init(uid_set_t* set);
+void btif_dm_cleanup(void);
+
/**
* BTIF callback to switch context from bte to btif
*/
#pragma once
+#include "btif_uid.h"
+
#include <hardware/bt_sock.h>
btsock_interface_t *btif_sock_get_interface(void);
-bt_status_t btif_sock_init(void);
+bt_status_t btif_sock_init(uid_set_t* uid_set);
void btif_sock_cleanup(void);
#ifndef BTIF_SOCK_L2CAP_H
#define BTIF_SOCK_L2CAP_H
+#include "btif_uid.h"
+
#include <hardware/bluetooth.h>
#define L2CAP_MASK_FIXED_CHANNEL 0x10000
-bt_status_t btsock_l2cap_init(int handle);
+bt_status_t btsock_l2cap_init(int handle, uid_set_t* set);
bt_status_t btsock_l2cap_cleanup();
bt_status_t btsock_l2cap_listen(const char* name, int channel,
- int* sock_fd, int flags);
+ int* sock_fd, int flags, int app_uid);
bt_status_t btsock_l2cap_connect(const bt_bdaddr_t *bd_addr,
- int channel, int* sock_fd, int flags);
+ int channel, int* sock_fd, int flags, int app_uid);
void btsock_l2cap_signaled(int fd, int flags, uint32_t user_id);
void on_l2cap_psm_assigned(int id, int psm);
#ifndef BTIF_SOCK_RFC_H
#define BTIF_SOCK_RFC_H
-bt_status_t btsock_rfc_init(int handle);
+#include "btif_uid.h"
+
+bt_status_t btsock_rfc_init(int handle, uid_set_t* set);
bt_status_t btsock_rfc_cleanup();
bt_status_t btsock_rfc_listen(const char* name, const uint8_t* uuid, int channel,
- int* sock_fd, int flags);
+ int* sock_fd, int flags, int app_uid);
bt_status_t btsock_rfc_connect(const bt_bdaddr_t *bd_addr, const uint8_t* uuid,
- int channel, int* sock_fd, int flags);
+ int channel, int* sock_fd, int flags, int app_uid);
void btsock_rfc_signaled(int fd, int flags, uint32_t user_id);
#endif
--- /dev/null
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#pragma once
+
+#include "bt_common.h"
+
+#include <hardware/bluetooth.h>
+
+struct uid_set_t;
+typedef struct uid_set_t uid_set_t;
+
+/**
+ * Creates a UID set to keep track of traffic per UID.
+ * Caller is responsible for destroying this object via uid_set_destroy().
+ */
+uid_set_t* uid_set_create();
+
+void uid_set_destroy(uid_set_t* set);
+
+void uid_set_add_tx(uid_set_t* set, int32_t app_uid, uint64_t bytes);
+void uid_set_add_rx(uid_set_t* set, int32_t app_uid, uint64_t bytes);
+
+/**
+ * Returns an array of bt_uid_traffic_t structs, where the end of the array
+ * is signaled by an element with app_uid == -1.
+ *
+ * The caller is responsible for calling osi_free() on the returned array.
+ */
+bt_uid_traffic_t* uid_set_read_and_clear(uid_set_t* set);
#include "btif_profile_queue.h"
#include "btif_sock.h"
#include "btif_storage.h"
+#include "btif_uid.h"
#include "btif_util.h"
#include "btu.h"
#include "device/include/controller.h"
static thread_t *bt_jni_workqueue_thread;
static const char *BT_JNI_WORKQUEUE_NAME = "bt_jni_workqueue";
+static uid_set_t* uid_set = NULL;
/************************************************************************************
** Static functions
/* callback to HAL */
if (status == BTA_SUCCESS)
{
+ uid_set = uid_set_create();
+
+ btif_dm_init(uid_set);
+
/* init rfcomm & l2cap api */
- btif_sock_init();
+ btif_sock_init(uid_set);
/* init pan */
btif_pan_init();
}
else
{
+ btif_dm_cleanup();
+
/* cleanup rfcomm & l2cap api */
btif_sock_cleanup();
BTIF_TRACE_DEBUG("BTIF DISABLE BLUETOOTH");
btif_dm_on_disable();
+ btif_dm_cleanup();
/* cleanup rfcomm & l2cap api */
btif_sock_cleanup();
btif_pan_cleanup();
BTA_DisableBluetooth();
+ if (uid_set) {
+ uid_set_destroy(uid_set);
+ uid_set = NULL;
+ }
+
return BT_STATUS_SUCCESS;
}
** Static variables
************************************************************************************/
static char btif_default_local_name[DEFAULT_LOCAL_NAME_MAX+1] = {'\0'};
+static uid_set_t* uid_set = NULL;
/******************************************************************************
** Static functions
osi_free(dm_sec->ble_key.p_key_value);
}
+void btif_dm_init(uid_set_t* set)
+{
+ uid_set = set;
+}
+
+void btif_dm_cleanup(void)
+{
+ uid_set = NULL;
+}
+
bt_status_t btif_in_execute_service_request(tBTA_SERVICE_ID service_id,
BOOLEAN b_enable)
{
energy_info.tx_time = p_ener_data->tx_time;
energy_info.idle_time = p_ener_data->idle_time;
energy_info.energy_used = p_ener_data->energy_used;
- HAL_CBACK(bt_hal_cbacks, energy_info_cb, &energy_info);
+
+ bt_uid_traffic_t* data = uid_set_read_and_clear(uid_set);
+ HAL_CBACK(bt_hal_cbacks, energy_info_cb, &energy_info, data);
+ osi_free(data);
break;
}
#endif
#include "btif_sock_sco.h"
#include "btif_sock_sdp.h"
#include "btif_sock_thread.h"
+#include "btif_uid.h"
#include "btif_util.h"
#include "osi/include/thread.h"
-static bt_status_t btsock_listen(btsock_type_t type, const char *service_name, const uint8_t *uuid, int channel, int *sock_fd, int flags);
-static bt_status_t btsock_connect(const bt_bdaddr_t *bd_addr, btsock_type_t type, const uint8_t *uuid, int channel, int *sock_fd, int flags);
+static bt_status_t btsock_listen(btsock_type_t type, const char *service_name, const uint8_t *uuid, int channel, int *sock_fd, int flags, int app_uid);
+static bt_status_t btsock_connect(const bt_bdaddr_t *bd_addr, btsock_type_t type, const uint8_t *uuid, int channel, int *sock_fd, int flags, int app_uid);
static void btsock_signaled(int fd, int type, int flags, uint32_t user_id);
return &interface;
}
-bt_status_t btif_sock_init(void) {
+bt_status_t btif_sock_init(uid_set_t* uid_set) {
assert(thread_handle == -1);
assert(thread == NULL);
goto error;
}
- bt_status_t status = btsock_rfc_init(thread_handle);
+ bt_status_t status = btsock_rfc_init(thread_handle, uid_set);
if (status != BT_STATUS_SUCCESS) {
LOG_ERROR(LOG_TAG, "%s error initializing RFCOMM sockets: %d", __func__, status);
goto error;
}
- status = btsock_l2cap_init(thread_handle);
+ status = btsock_l2cap_init(thread_handle, uid_set);
if (status != BT_STATUS_SUCCESS) {
LOG_ERROR(LOG_TAG, "%s error initializing L2CAP sockets: %d", __func__, status);
goto error;
if (thread_handle != -1)
btsock_thread_exit(thread_handle);
thread_handle = -1;
+ uid_set = NULL;
return BT_STATUS_FAIL;
}
thread = NULL;
}
-static bt_status_t btsock_listen(btsock_type_t type, const char *service_name, const uint8_t *service_uuid, int channel, int *sock_fd, int flags) {
+static bt_status_t btsock_listen(btsock_type_t type, const char *service_name, const uint8_t *service_uuid, int channel, int *sock_fd, int flags, int app_uid) {
if((flags & BTSOCK_FLAG_NO_SDP) == 0) {
assert(service_uuid != NULL || channel > 0);
assert(sock_fd != NULL);
switch (type) {
case BTSOCK_RFCOMM:
- status = btsock_rfc_listen(service_name, service_uuid, channel, sock_fd, flags);
+ status = btsock_rfc_listen(service_name, service_uuid, channel, sock_fd, flags, app_uid);
break;
case BTSOCK_L2CAP:
- status = btsock_l2cap_listen(service_name, channel, sock_fd, flags);
+ status = btsock_l2cap_listen(service_name, channel, sock_fd, flags, app_uid);
break;
case BTSOCK_SCO:
return status;
}
-static bt_status_t btsock_connect(const bt_bdaddr_t *bd_addr, btsock_type_t type, const uint8_t *uuid, int channel, int *sock_fd, int flags) {
+static bt_status_t btsock_connect(const bt_bdaddr_t *bd_addr, btsock_type_t type, const uint8_t *uuid, int channel, int *sock_fd, int flags, int app_uid) {
assert(uuid != NULL || channel > 0);
assert(bd_addr != NULL);
assert(sock_fd != NULL);
switch (type) {
case BTSOCK_RFCOMM:
- status = btsock_rfc_connect(bd_addr, uuid, channel, sock_fd, flags);
+ status = btsock_rfc_connect(bd_addr, uuid, channel, sock_fd, flags, app_uid);
break;
case BTSOCK_L2CAP:
- status = btsock_l2cap_connect(bd_addr, channel, sock_fd, flags);
+ status = btsock_l2cap_connect(bd_addr, channel, sock_fd, flags, app_uid);
break;
case BTSOCK_SCO:
#include "btif_sock_sdp.h"
#include "btif_sock_thread.h"
#include "btif_sock_util.h"
+#include "btif_uid.h"
#include "btif_util.h"
#include "btm_api.h"
#include "btm_int.h"
bt_bdaddr_t addr; //other side's address
char name[256]; //user-friendly name of the service
uint32_t id; //just a tag to find this struct
+ int app_uid; // The UID of the app who requested this socket
int handle; //handle from lower layers
unsigned security; //security flags
int channel; //channel (fixed_chan) or PSM (!fixed_chan)
static pthread_mutex_t state_lock;
l2cap_socket *socks = NULL;
+static uid_set_t* uid_set = NULL;
static int pth = -1;
static void btsock_l2cap_cbk(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data);
sock->connected = FALSE;
sock->handle = 0;
sock->server_psm_sent = FALSE;
+ sock->app_uid = -1;
if (name)
strncpy(sock->name, name, sizeof(sock->name) - 1);
return NULL;
}
-bt_status_t btsock_l2cap_init(int handle)
+bt_status_t btsock_l2cap_init(int handle, uid_set_t* set)
{
APPL_TRACE_DEBUG("btsock_l2cap_init...");
pthread_mutex_lock(&state_lock);
pth = handle;
socks = NULL;
+ uid_set = set;
pthread_mutex_unlock(&state_lock);
return BT_STATUS_SUCCESS;
accept_rs->fixed_chan = sock->fixed_chan;
accept_rs->channel = sock->channel;
accept_rs->handle = sock->handle;
+ accept_rs->app_uid = sock->app_uid;
sock->handle = -1; /* We should no longer associate this handle with the server socket */
/* Swap IDs to hand over the GAP connection to the accepted socket, and start a new server on
accept_rs->security = sock->security;
accept_rs->fixed_chan = sock->fixed_chan;
accept_rs->channel = sock->channel;
+ accept_rs->app_uid = sock->app_uid;
//if we do not set a callback, this socket will be dropped */
*(p_open->p_p_cback) = (void*)btsock_l2cap_cbk;
pthread_mutex_unlock(&state_lock);
}
-static void on_l2cap_write_done(void* req_id, uint32_t id)
+static void on_l2cap_write_done(void* req_id, uint16_t len, uint32_t id)
{
l2cap_socket *sock;
osi_free(req_id); //free the buffer
}
+ int app_uid = -1;
+
pthread_mutex_lock(&state_lock);
sock = btsock_l2cap_find_by_id_l(id);
- if (sock && !sock->outgoing_congest) {
- //monitor the fd for any outgoing data
- APPL_TRACE_DEBUG("on_l2cap_write_done: adding fd to btsock_thread...");
- btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD, sock->id);
+ if (sock) {
+ app_uid = sock->app_uid;
+ if (!sock->outgoing_congest) {
+ //monitor the fd for any outgoing data
+ APPL_TRACE_DEBUG("on_l2cap_write_done: adding fd to btsock_thread...");
+ btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD, sock->id);
+ }
}
pthread_mutex_unlock(&state_lock);
+
+ uid_set_add_tx(uid_set, app_uid, len);
}
-static void on_l2cap_write_fixed_done(void* req_id, uint32_t id)
+static void on_l2cap_write_fixed_done(void* req_id, uint16_t len, uint32_t id)
{
l2cap_socket *sock;
osi_free(req_id); //free the buffer
}
+ int app_uid = -1;
pthread_mutex_lock(&state_lock);
sock = btsock_l2cap_find_by_id_l(id);
- if (sock && !sock->outgoing_congest) {
- //monitor the fd for any outgoing data
- btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD, sock->id);
+ if (sock) {
+ app_uid = sock->app_uid;
+ if (!sock->outgoing_congest) {
+ //monitor the fd for any outgoing data
+ btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD, sock->id);
+ }
}
pthread_mutex_unlock(&state_lock);
+
+ uid_set_add_tx(uid_set, app_uid, len);
}
static void on_l2cap_data_ind(tBTA_JV *evt, uint32_t id)
{
l2cap_socket *sock;
+ int app_uid = -1;
+ UINT32 bytes_read = 0;
+
pthread_mutex_lock(&state_lock);
sock = btsock_l2cap_find_by_id_l(id);
if (sock) {
+ app_uid = sock->app_uid;
+
if (sock->fixed_chan) { /* we do these differently */
tBTA_JV_LE_DATA_IND *p_le_data_ind = &evt->le_data_ind;
BT_HDR *p_buf = p_le_data_ind->p_buf;
uint8_t *data = (uint8_t*)(p_buf + 1) + p_buf->offset;
- if (packet_put_tail_l(sock, data, p_buf->len))
+ if (packet_put_tail_l(sock, data, p_buf->len)) {
+ bytes_read = p_buf->len;
btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_WR, sock->id);
- else {//connection must be dropped
+ } else {//connection must be dropped
APPL_TRACE_DEBUG("on_l2cap_data_ind() unable to push data to socket - closing"
" fixed channel");
BTA_JvL2capCloseLE(sock->handle);
if (BTA_JvL2capReady(sock->handle, &count) == BTA_JV_SUCCESS) {
if (BTA_JvL2capRead(sock->handle, sock->id, buffer, count) == BTA_JV_SUCCESS) {
- if (packet_put_tail_l(sock, buffer, count))
+ if (packet_put_tail_l(sock, buffer, count)) {
+ bytes_read = count;
btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_WR,
sock->id);
- else {//connection must be dropped
+ } else {//connection must be dropped
APPL_TRACE_DEBUG("on_l2cap_data_ind() unable to push data to socket"
" - closing channel");
BTA_JvL2capClose(sock->handle);
}
}
pthread_mutex_unlock(&state_lock);
+
+ uid_set_add_rx(uid_set, app_uid, bytes_read);
}
static void btsock_l2cap_cbk(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data)
case BTA_JV_L2CAP_WRITE_EVT:
APPL_TRACE_DEBUG("BTA_JV_L2CAP_WRITE_EVT: id: %u", sock_id);
- on_l2cap_write_done(UINT_TO_PTR(p_data->l2c_write.req_id), sock_id);
+ on_l2cap_write_done(UINT_TO_PTR(p_data->l2c_write.req_id), p_data->l2c_write.len, sock_id);
break;
case BTA_JV_L2CAP_WRITE_FIXED_EVT:
APPL_TRACE_DEBUG("BTA_JV_L2CAP_WRITE_FIXED_EVT: id: %u", sock_id);
- on_l2cap_write_fixed_done(UINT_TO_PTR(p_data->l2c_write_fixed.req_id), sock_id);
+ on_l2cap_write_fixed_done(UINT_TO_PTR(p_data->l2c_write_fixed.req_id), p_data->l2c_write.len, sock_id);
break;
case BTA_JV_L2CAP_CONG_EVT:
}
static bt_status_t btsock_l2cap_listen_or_connect(const char *name, const bt_bdaddr_t *addr,
- int channel, int* sock_fd, int flags, char listen)
+ int channel, int* sock_fd, int flags, char listen, int app_uid)
{
bt_status_t stat;
int fixed_chan = 1;
sock->fixed_chan = fixed_chan;
sock->channel = channel;
+ sock->app_uid = app_uid;
stat = BT_STATUS_SUCCESS;
return stat;
}
-bt_status_t btsock_l2cap_listen(const char* name, int channel, int* sock_fd, int flags)
+bt_status_t btsock_l2cap_listen(const char* name, int channel, int* sock_fd, int flags, int app_uid)
{
- return btsock_l2cap_listen_or_connect(name, NULL, channel, sock_fd, flags, 1);
+ return btsock_l2cap_listen_or_connect(name, NULL, channel, sock_fd, flags, 1, app_uid);
}
-bt_status_t btsock_l2cap_connect(const bt_bdaddr_t *bd_addr, int channel, int* sock_fd, int flags)
+bt_status_t btsock_l2cap_connect(const bt_bdaddr_t *bd_addr, int channel, int* sock_fd, int flags, int app_uid)
{
- return btsock_l2cap_listen_or_connect(NULL, bd_addr, channel, sock_fd, flags, 0);
+ return btsock_l2cap_listen_or_connect(NULL, bd_addr, channel, sock_fd, flags, 0, app_uid);
}
/* return TRUE if we have more to send and should wait for user readiness, FALSE else
PTR_TO_UINT(buffer), btsock_l2cap_cbk, buffer, count,
UINT_TO_PTR(user_id)) != BTA_JV_SUCCESS) {
// On fail, free the buffer
- on_l2cap_write_fixed_done(buffer, user_id);
+ on_l2cap_write_fixed_done(buffer, count, user_id);
}
} else {
if(BTA_JvL2capWrite(sock->handle, PTR_TO_UINT(buffer), buffer, count,
UINT_TO_PTR(user_id)) != BTA_JV_SUCCESS) {
// On fail, free the buffer
- on_l2cap_write_done(buffer, user_id);
+ on_l2cap_write_done(buffer, count, user_id);
}
}
} else {
#include "btif_sock_sdp.h"
#include "btif_sock_thread.h"
#include "btif_sock_util.h"
+#include "btif_uid.h"
#include "btif_util.h"
#include "btm_api.h"
#include "btm_int.h"
char service_name[256];
int fd;
int app_fd; // Temporary storage for the half of the socketpair that's sent back to upper layers.
+ int app_uid; // UID of the app for which this socket was created.
int mtu;
uint8_t *packet;
int sdp_handle;
static uint32_t rfc_slot_id;
static volatile int pth = -1; // poll thread handle
static pthread_mutex_t slot_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+static uid_set_t* uid_set = NULL;
static rfc_slot_t *find_free_slot(void);
static void cleanup_rfc_slot(rfc_slot_t *rs);
return pth != -1;
}
-bt_status_t btsock_rfc_init(int poll_thread_handle) {
+bt_status_t btsock_rfc_init(int poll_thread_handle, uid_set_t* set) {
pth = poll_thread_handle;
+ uid_set = set;
memset(rfc_slots, 0, sizeof(rfc_slots));
for (size_t i = 0; i < ARRAY_SIZE(rfc_slots); ++i) {
void btsock_rfc_cleanup(void) {
pth = -1;
+ uid_set = NULL;
pthread_mutex_lock(&slot_lock);
for (size_t i = 0; i < ARRAY_SIZE(rfc_slots); ++i) {
slot->app_fd = fds[1];
slot->security = security;
slot->scn = channel;
+ slot->app_uid = -1;
if(!is_uuid_empty(uuid)) {
memcpy(slot->service_uuid, uuid, sizeof(slot->service_uuid));
accept_rs->role = srv_rs->role;
accept_rs->rfc_handle = open_handle;
accept_rs->rfc_port_handle = BTA_JvRfcommGetPortHdl(open_handle);
+ accept_rs->app_uid = srv_rs->app_uid;
srv_rs->rfc_handle = new_listen_handle;
srv_rs->rfc_port_handle = BTA_JvRfcommGetPortHdl(new_listen_handle);
return accept_rs;
}
-bt_status_t btsock_rfc_listen(const char *service_name, const uint8_t *service_uuid, int channel, int *sock_fd, int flags) {
+bt_status_t btsock_rfc_listen(const char *service_name, const uint8_t *service_uuid, int channel, int *sock_fd, int flags, int app_uid) {
assert(sock_fd != NULL);
assert((service_uuid != NULL)
|| (channel >= 1 && channel <= MAX_RFC_CHANNEL)
- Try to simply remove the = -1 to free the FD at rs cleanup.*/
// close(rs->app_fd);
slot->app_fd = INVALID_FD; // Drop our reference to the fd.
+ slot->app_uid = app_uid;
btsock_thread_add_fd(pth, slot->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_EXCEPTION, slot->id);
status = BT_STATUS_SUCCESS;
return status;
}
-bt_status_t btsock_rfc_connect(const bt_bdaddr_t *bd_addr, const uint8_t *service_uuid, int channel, int *sock_fd, int flags) {
+bt_status_t btsock_rfc_connect(const bt_bdaddr_t *bd_addr, const uint8_t *service_uuid, int channel, int *sock_fd, int flags, int app_uid) {
assert(sock_fd != NULL);
assert(service_uuid != NULL || (channel >= 1 && channel <= MAX_RFC_CHANNEL));
*sock_fd = slot->app_fd; // Transfer ownership of fd to caller.
slot->app_fd = INVALID_FD; // Drop our reference to the fd.
+ slot->app_uid = app_uid;
btsock_thread_add_fd(pth, slot->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD, slot->id);
status = BT_STATUS_SUCCESS;
}
static void on_rfc_write_done(UNUSED_ATTR tBTA_JV_RFCOMM_WRITE *p, uint32_t id) {
+ int app_uid = -1;
pthread_mutex_lock(&slot_lock);
rfc_slot_t *slot = find_rfc_slot_by_id(id);
- if (slot && !slot->f.outgoing_congest)
- btsock_thread_add_fd(pth, slot->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD, slot->id);
+ if (slot) {
+ app_uid = slot->app_uid;
+ if (!slot->f.outgoing_congest) {
+ btsock_thread_add_fd(pth, slot->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD, slot->id);
+ }
+ }
pthread_mutex_unlock(&slot_lock);
+
+ uid_set_add_tx(uid_set, app_uid, p->len);
}
static void on_rfc_outgoing_congest(tBTA_JV_RFCOMM_CONG *p, uint32_t id) {
case BTA_JV_RFCOMM_READ_EVT:
case BTA_JV_RFCOMM_DATA_IND_EVT:
- // Unused.
+ // unused
break;
default:
}
int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf) {
+ int app_uid = -1;
+ uint64_t bytes_rx = 0;
+
pthread_mutex_lock(&slot_lock);
int ret = 0;
if (!slot)
goto out;
+ app_uid = slot->app_uid;
+ bytes_rx = p_buf->len;
+
if (list_is_empty(slot->incoming_queue)) {
switch (send_data_to_app(slot->fd, p_buf)) {
case SENT_NONE:
out:;
pthread_mutex_unlock(&slot_lock);
+
+ uid_set_add_rx(uid_set, app_uid, bytes_rx);
+
return ret; // Return 0 to disable data flow.
}
--- /dev/null
+/*
+ * Copyright (C) 2015 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.c
+ *
+ * Description: Contains data structures and functions for keeping track of
+ * socket usage per app UID.
+ *
+ ***********************************************************************************/
+#define LOG_TAG "bt_uid_set"
+#include "bt_common.h"
+#include "btif_uid.h"
+
+#include <log/log.h>
+#include <pthread.h>
+
+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 {
+ pthread_mutex_t lock;
+ uid_set_node_t* head;
+} uid_set_t;
+
+uid_set_t* uid_set_create(void) {
+ uid_set_t* set = osi_calloc(sizeof(uid_set_t));
+ pthread_mutex_init(&set->lock, NULL);
+ return set;
+}
+
+void uid_set_destroy(uid_set_t* set) {
+ pthread_mutex_lock(&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;
+ pthread_mutex_unlock(&set->lock);
+ pthread_mutex_destroy(&set->lock);
+ 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 = 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;
+ }
+
+ pthread_mutex_lock(&set->lock);
+ uid_set_node_t* node = uid_set_find_or_create_node(set, app_uid);
+ node->data.tx_bytes += bytes;
+ pthread_mutex_unlock(&set->lock);
+}
+
+void uid_set_add_rx(uid_set_t* set, int32_t app_uid, uint64_t bytes) {
+ if (app_uid == -1 || bytes == 0) {
+ return;
+ }
+
+ pthread_mutex_lock(&set->lock);
+ uid_set_node_t* node = uid_set_find_or_create_node(set, app_uid);
+ node->data.rx_bytes += bytes;
+ pthread_mutex_unlock(&set->lock);
+}
+
+bt_uid_traffic_t* uid_set_read_and_clear(uid_set_t* set) {
+ pthread_mutex_lock(&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 = 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;
+
+ pthread_mutex_unlock(&set->lock);
+
+ return result;
+}
../btif/src/btif_sdp_server.c \
../btif/src/btif_sock_util.c \
../btif/src/btif_storage.c \
+ ../btif/src/btif_uid.c \
../btif/src/btif_util.c \
../btif/src/stack_manager.c
sleep(timeout_in_sec);
}
+ const int app_uid = 0;
+
if (sco_listen) {
CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
fprintf(stdout, "BT adapter is up\n");
const btsock_interface_t *sock = bt_interface->get_profile_interface(BT_PROFILE_SOCKETS_ID);
int rfcomm_fd = INVALID_FD;
- int error = sock->listen(BTSOCK_RFCOMM, "meow", (const uint8_t *)&HFP_AG_UUID, 0, &rfcomm_fd, 0);
+ int error = sock->listen(BTSOCK_RFCOMM, "meow", (const uint8_t *)&HFP_AG_UUID, 0, &rfcomm_fd, 0, app_uid);
if (error != BT_STATUS_SUCCESS) {
fprintf(stderr, "Unable to listen for incoming RFCOMM socket: %d\n", error);
exit(1);
}
int sock_fd = INVALID_FD;
- error = sock->listen(BTSOCK_SCO, NULL, NULL, 5, &sock_fd, 0);
+ error = sock->listen(BTSOCK_SCO, NULL, NULL, 5, &sock_fd, 0, app_uid);
if (error != BT_STATUS_SUCCESS) {
fprintf(stderr, "Unable to listen for incoming SCO sockets: %d\n", error);
exit(1);
const btsock_interface_t *sock = bt_interface->get_profile_interface(BT_PROFILE_SOCKETS_ID);
int rfcomm_fd = INVALID_FD;
- int error = sock->connect(&bt_remote_bdaddr, BTSOCK_RFCOMM, (const uint8_t *)&HFP_AG_UUID, 0, &rfcomm_fd, 0);
+ int error = sock->connect(&bt_remote_bdaddr, BTSOCK_RFCOMM, (const uint8_t *)&HFP_AG_UUID, 0, &rfcomm_fd, 0, app_uid);
if (error != BT_STATUS_SUCCESS) {
fprintf(stderr, "Unable to connect to RFCOMM socket: %d.\n", error);
exit(1);
fprintf(stdout, "Establishing SCO connection...\n");
int sock_fd = INVALID_FD;
- error = sock->connect(&bt_remote_bdaddr, BTSOCK_SCO, NULL, 5, &sock_fd, 0);
+ error = sock->connect(&bt_remote_bdaddr, BTSOCK_SCO, NULL, 5, &sock_fd, 0, app_uid);
if (error != BT_STATUS_SUCCESS) {
fprintf(stderr, "Unable to connect to SCO socket: %d.\n", error);
exit(1);