OSDN Git Service

Add socket tx/rx accounting
authorAdam Lesinski <adamlesinski@google.com>
Thu, 3 Dec 2015 06:15:08 +0000 (22:15 -0800)
committerAdam Lesinski <adamlesinski@google.com>
Thu, 21 Jan 2016 00:59:02 +0000 (00:59 +0000)
Records network traffic going over bluetooth sockets. This patch adds support
for L2CAP and RFCOMM.

Bug:26039657
Change-Id: Idb860b367b429fa5ef41d02684a5494a668ee8ed

14 files changed:
btif/BUILD.gn
btif/include/btif_dm.h
btif/include/btif_sock.h
btif/include/btif_sock_l2cap.h
btif/include/btif_sock_rfc.h
btif/include/btif_uid.h [new file with mode: 0644]
btif/src/btif_core.c
btif/src/btif_dm.c
btif/src/btif_sock.c
btif/src/btif_sock_l2cap.c
btif/src/btif_sock_rfc.c
btif/src/btif_uid.c [new file with mode: 0644]
main/Android.mk
tools/bdtool/bdtool.c

index ef5de76..77e98ec 100644 (file)
@@ -50,6 +50,7 @@ static_library("btif") {
     "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",
   ]
index fb9bb4d..72ee378 100644 (file)
 #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
  */
index 1747230..4ad4ab6 100644 (file)
 
 #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);
index 065aa48..94f4a07 100644 (file)
@@ -5,16 +5,18 @@
 #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);
 
index b36ec1f..7d93856 100644 (file)
 #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
diff --git a/btif/include/btif_uid.h b/btif/include/btif_uid.h
new file mode 100644 (file)
index 0000000..92eeac3
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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);
index 7b29399..eb811f4 100644 (file)
@@ -59,6 +59,7 @@
 #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"
@@ -130,6 +131,7 @@ static UINT8 btif_dut_mode = 0;
 
 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
@@ -545,8 +547,12 @@ void btif_enable_bluetooth_evt(tBTA_STATUS status)
     /* 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();
@@ -562,6 +568,8 @@ void btif_enable_bluetooth_evt(tBTA_STATUS status)
     }
     else
     {
+        btif_dm_cleanup();
+
         /* cleanup rfcomm & l2cap api */
         btif_sock_cleanup();
 
@@ -587,11 +595,17 @@ bt_status_t btif_disable_bluetooth(void)
     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;
 }
 
index 4888700..1485076 100644 (file)
@@ -191,6 +191,7 @@ static BOOLEAN btif_dm_inquiry_in_progress = FALSE;
 **  Static variables
 ************************************************************************************/
 static char btif_default_local_name[DEFAULT_LOCAL_NAME_MAX+1] = {'\0'};
+static uid_set_t* uid_set = NULL;
 
 /******************************************************************************
 **  Static functions
@@ -265,6 +266,16 @@ static void btif_dm_data_free(uint16_t event, tBTA_DM_SEC *dm_sec)
         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)
 {
@@ -1964,7 +1975,10 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
             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
index 4ffbb45..3b43545 100644 (file)
 #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);
 
@@ -52,7 +53,7 @@ btsock_interface_t *btif_sock_get_interface(void) {
   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);
 
@@ -63,13 +64,13 @@ bt_status_t btif_sock_init(void) {
     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;
@@ -97,6 +98,7 @@ error:;
   if (thread_handle != -1)
     btsock_thread_exit(thread_handle);
   thread_handle = -1;
+  uid_set = NULL;
   return BT_STATUS_FAIL;
 }
 
@@ -115,7 +117,7 @@ void btif_sock_cleanup(void) {
   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);
@@ -126,10 +128,10 @@ static bt_status_t btsock_listen(btsock_type_t type, const char *service_name, c
 
   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:
@@ -144,7 +146,7 @@ static bt_status_t btsock_listen(btsock_type_t type, const char *service_name, c
   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);
@@ -154,11 +156,11 @@ static bt_status_t btsock_connect(const bt_bdaddr_t *bd_addr, btsock_type_t type
 
   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:
index 12c301d..c304346 100644 (file)
@@ -40,6 +40,7 @@
 #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"
@@ -67,6 +68,7 @@ typedef struct l2cap_socket {
     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)
@@ -90,6 +92,7 @@ static bt_status_t btSock_start_l2cap_server_l(l2cap_socket *sock);
 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);
@@ -321,6 +324,7 @@ static l2cap_socket *btsock_l2cap_alloc_l(const char *name, const bt_bdaddr_t *a
     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);
@@ -359,12 +363,13 @@ fail_alloc:
     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;
@@ -468,6 +473,7 @@ static void on_srv_l2cap_psm_connect_l(tBTA_JV_L2CAP_OPEN *p_open, l2cap_socket
     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
@@ -514,6 +520,7 @@ static void on_srv_l2cap_le_connect_l(tBTA_JV_L2CAP_LE_OPEN *p_open, l2cap_socke
         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;
@@ -637,7 +644,7 @@ static void on_l2cap_outgoing_congest(tBTA_JV_L2CAP_CONG *p, uint32_t id)
     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;
 
@@ -645,17 +652,24 @@ static void on_l2cap_write_done(void* req_id, uint32_t id)
         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;
 
@@ -663,31 +677,43 @@ static void on_l2cap_write_fixed_done(void* req_id, uint32_t id)
         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);
@@ -701,10 +727,11 @@ static void on_l2cap_data_ind(tBTA_JV *evt, uint32_t id)
 
             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);
@@ -715,6 +742,8 @@ static void on_l2cap_data_ind(tBTA_JV *evt, uint32_t id)
         }
     }
     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)
@@ -755,12 +784,12 @@ 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:
@@ -849,7 +878,7 @@ static bt_status_t btSock_start_l2cap_server_l(l2cap_socket *sock) {
 }
 
 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;
@@ -879,6 +908,7 @@ static bt_status_t btsock_l2cap_listen_or_connect(const char *name, const bt_bda
 
     sock->fixed_chan = fixed_chan;
     sock->channel = channel;
+    sock->app_uid = app_uid;
 
     stat = BT_STATUS_SUCCESS;
 
@@ -924,14 +954,14 @@ static bt_status_t btsock_l2cap_listen_or_connect(const char *name, const bt_bda
     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
@@ -1019,13 +1049,13 @@ void btsock_l2cap_signaled(int fd, int flags, uint32_t user_id)
                                     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 {
index 253708e..c0a9414 100644 (file)
@@ -39,6 +39,7 @@
 #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"
@@ -80,6 +81,7 @@ typedef struct {
   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;
@@ -93,6 +95,7 @@ static rfc_slot_t rfc_slots[MAX_RFC_CHANNEL];
 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);
@@ -104,8 +107,9 @@ static bool is_init_done(void) {
   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) {
@@ -124,6 +128,7 @@ bt_status_t btsock_rfc_init(int poll_thread_handle) {
 
 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) {
@@ -202,6 +207,7 @@ static rfc_slot_t *alloc_rfc_slot(const bt_bdaddr_t *addr, const char *name, con
   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));
@@ -238,6 +244,7 @@ static rfc_slot_t *create_srv_accept_rfc_slot(rfc_slot_t *srv_rs, const bt_bdadd
   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);
@@ -252,7 +259,7 @@ static rfc_slot_t *create_srv_accept_rfc_slot(rfc_slot_t *srv_rs, const bt_bdadd
   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)
@@ -298,6 +305,7 @@ bt_status_t btsock_rfc_listen(const char *service_name, const uint8_t *service_u
     - 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;
@@ -307,7 +315,7 @@ out:;
   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));
 
@@ -357,6 +365,7 @@ bt_status_t btsock_rfc_connect(const bt_bdaddr_t *bd_addr, const uint8_t *servic
 
   *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;
 
@@ -533,13 +542,20 @@ static void on_rfc_close(UNUSED_ATTR tBTA_JV_RFCOMM_CLOSE *p_close, uint32_t id)
 }
 
 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) {
@@ -592,7 +608,7 @@ static void *rfcomm_cback(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data) {
 
     case BTA_JV_RFCOMM_READ_EVT:
     case BTA_JV_RFCOMM_DATA_IND_EVT:
-      // Unused.
+      // unused
       break;
 
     default:
@@ -815,6 +831,9 @@ out:;
 }
 
 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;
@@ -823,6 +842,9 @@ int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf) {
   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:
@@ -847,6 +869,9 @@ int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf) {
 
 out:;
   pthread_mutex_unlock(&slot_lock);
+
+  uid_set_add_rx(uid_set, app_uid, bytes_rx);
+
   return ret;  // Return 0 to disable data flow.
 }
 
diff --git a/btif/src/btif_uid.c b/btif/src/btif_uid.c
new file mode 100644 (file)
index 0000000..17573a9
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * 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;
+}
index c68c17f..d355dd5 100644 (file)
@@ -54,6 +54,7 @@ LOCAL_SRC_FILES += \
     ../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
 
index d0d0cc7..0f81685 100644 (file)
@@ -188,6 +188,8 @@ int main(int argc, char **argv) {
     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");
@@ -199,14 +201,14 @@ int main(int argc, char **argv) {
     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);
@@ -227,7 +229,7 @@ int main(int argc, char **argv) {
     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);
@@ -238,7 +240,7 @@ int main(int argc, char **argv) {
     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);