Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 053048d9 authored by Adam Lesinski's avatar Adam Lesinski Committed by Android (Google) Code Review
Browse files

Merge "Add traffic accounting to Bluetooth App."

parents dfc98da6 cbe58102
Loading
Loading
Loading
Loading
+44 −9
Original line number Diff line number Diff line
@@ -48,6 +48,11 @@ static jmethodID method_acquireWakeLock;
static jmethodID method_releaseWakeLock;
static jmethodID method_energyInfo;

static struct {
    jclass clazz;
    jmethodID constructor;
} android_bluetooth_UidTraffic;

static const bt_interface_t *sBluetoothInterface = NULL;
static const btsock_interface_t *sBluetoothSocketInterface = NULL;
static JNIEnv *callbackEnv = NULL;
@@ -449,18 +454,36 @@ static void le_test_mode_recv_callback (bt_status_t status, uint16_t packet_coun
    ALOGV("%s: status:%d packet_count:%d ", __FUNCTION__, status, packet_count);
}

static void energy_info_recv_callback(bt_activity_energy_info *p_energy_info)
static void energy_info_recv_callback(bt_activity_energy_info *p_energy_info,
                                      bt_uid_traffic_t* uid_data)
{
    if (!checkCallbackThread()) {
       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
       return;
    }

    jsize len = 0;
    for (bt_uid_traffic_t* data = uid_data; data->app_uid != -1; data++) {
        len++;
    }

    jobjectArray array = callbackEnv->NewObjectArray(len, android_bluetooth_UidTraffic.clazz, NULL);
    jsize i = 0;
    for (bt_uid_traffic_t* data = uid_data; data->app_uid != -1; data++) {
        jobject uidObj = callbackEnv->NewObject(android_bluetooth_UidTraffic.clazz,
                                                android_bluetooth_UidTraffic.constructor,
                                                (jint) data->app_uid, (jlong) data->rx_bytes,
                                                (jlong) data->tx_bytes);
        callbackEnv->SetObjectArrayElement(array, i++, uidObj);
        callbackEnv->DeleteLocalRef(uidObj);
    }

    callbackEnv->CallVoidMethod(sJniAdapterServiceObj, method_energyInfo, p_energy_info->status,
        p_energy_info->ctrl_state, p_energy_info->tx_time, p_energy_info->rx_time,
        p_energy_info->idle_time, p_energy_info->energy_used);
        p_energy_info->idle_time, p_energy_info->energy_used, array);

    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    callbackEnv->DeleteLocalRef(array);
}

static bt_callbacks_t sBluetoothCallbacks = {
@@ -605,6 +628,11 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
    int err;
    hw_module_t* module;


    jclass jniUidTrafficClass = env->FindClass("android/bluetooth/UidTraffic");
    android_bluetooth_UidTraffic.constructor = env->GetMethodID(jniUidTrafficClass,
                                                                "<init>", "(IJJ)V");

    jclass jniCallbackClass =
        env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
    sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
@@ -636,7 +664,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
    method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z");
    method_acquireWakeLock = env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z");
    method_releaseWakeLock = env->GetMethodID(clazz, "releaseWakeLock", "(Ljava/lang/String;)Z");
    method_energyInfo = env->GetMethodID(clazz, "energyInfoCallback", "(IIJJJJ)V");
    method_energyInfo = env->GetMethodID(clazz, "energyInfoCallback", "(IIJJJJ[Landroid/bluetooth/UidTraffic;)V");

    char value[PROPERTY_VALUE_MAX];
    property_get("bluetooth.mock_stack", value, "");
@@ -662,6 +690,9 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
static bool initNative(JNIEnv* env, jobject obj) {
    ALOGV("%s:",__FUNCTION__);

    android_bluetooth_UidTraffic.clazz = (jclass) env->NewGlobalRef(
            env->FindClass("android/bluetooth/UidTraffic"));

    sJniAdapterServiceObj = env->NewGlobalRef(obj);
    sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));

@@ -701,6 +732,8 @@ static bool cleanupNative(JNIEnv *env, jobject obj) {

    env->DeleteGlobalRef(sJniCallbacksObj);
    env->DeleteGlobalRef(sJniAdapterServiceObj);
    env->DeleteGlobalRef(android_bluetooth_UidTraffic.clazz);
    android_bluetooth_UidTraffic.clazz = NULL;
    return JNI_TRUE;
}

@@ -1052,7 +1085,7 @@ static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray add
}

static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type,
                                   jbyteArray uuidObj, jint channel, jint flag) {
                                   jbyteArray uuidObj, jint channel, jint flag, jint callingUid) {
    jbyte *addr = NULL, *uuid = NULL;
    int socket_fd;
    bt_status_t status;
@@ -1074,7 +1107,8 @@ static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address,
    }

    if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type,
                       (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
                       (const uint8_t*) uuid, channel, &socket_fd, flag, callingUid))
            != BT_STATUS_SUCCESS) {
        ALOGE("Socket connection failed: %d", status);
        goto Fail;
    }
@@ -1097,7 +1131,7 @@ Fail:

static int createSocketChannelNative(JNIEnv *env, jobject object, jint type,
                                     jstring name_str, jbyteArray uuidObj,
                                     jint channel, jint flag) {
                                     jint channel, jint flag, jint callingUid) {
    const char *service_name = NULL;
    jbyte *uuid = NULL;
    int socket_fd;
@@ -1119,7 +1153,8 @@ static int createSocketChannelNative(JNIEnv *env, jobject object, jint type,
        }
    }
    if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name,
                       (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
                       (const uint8_t*) uuid, channel, &socket_fd, flag, callingUid))
            != BT_STATUS_SUCCESS) {
        ALOGE("Socket listen failed: %d", status);
        goto Fail;
    }
@@ -1202,8 +1237,8 @@ static JNINativeMethod sMethods[] = {
    {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
    {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
    {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
    {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative},
    {"createSocketChannelNative", "(ILjava/lang/String;[BII)I",
    {"connectSocketNative", "([BI[BIII)I", (void*) connectSocketNative},
    {"createSocketChannelNative", "(ILjava/lang/String;[BIII)I",
     (void*) createSocketChannelNative},
    {"configHciSnoopLogNative", "(Z)Z", (void*) configHciSnoopLogNative},
    {"alarmFiredNative", "()V", (void *) alarmFiredNative},
+49 −9
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.bluetooth.IBluetoothManager;
import android.bluetooth.IBluetoothManagerCallback;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.OobData;
import android.bluetooth.UidTraffic;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -57,6 +58,7 @@ import android.util.EventLog;
import android.util.Log;
import android.util.Pair;

import android.util.SparseArray;
import com.android.bluetooth.a2dp.A2dpService;
import com.android.bluetooth.a2dp.A2dpSinkService;
import com.android.bluetooth.hid.HidService;
@@ -72,6 +74,7 @@ import java.io.FileDescriptor;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
import java.util.Map;
@@ -97,6 +100,7 @@ public class AdapterService extends Service {
    private int mRxTimeTotalMs;
    private int mIdleTimeTotalMs;
    private int mEnergyUsedTotalVoltAmpSecMicro;
    private SparseArray<UidTraffic> mUidTraffic = new SparseArray<>();

    private final ArrayList<ProfileService> mProfiles = new ArrayList<ProfileService>();

@@ -1855,7 +1859,7 @@ public class AdapterService extends Service {
                                              ParcelUuid uuid, int port, int flag) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()),
                   type, Utils.uuidToByteArray(uuid), port, flag);
                   type, Utils.uuidToByteArray(uuid), port, flag, Binder.getCallingUid());
        if (fd < 0) {
            errorLog("Failed to connect socket");
            return null;
@@ -1867,7 +1871,7 @@ public class AdapterService extends Service {
                                                    ParcelUuid uuid, int port, int flag) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        int fd =  createSocketChannelNative(type, serviceName,
                                 Utils.uuidToByteArray(uuid), port, flag);
                                 Utils.uuidToByteArray(uuid), port, flag, Binder.getCallingUid());
        if (fd < 0) {
            errorLog("Failed to create socket channel");
            return null;
@@ -1943,7 +1947,32 @@ public class AdapterService extends Service {
        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission");
        BluetoothActivityEnergyInfo info =
            new BluetoothActivityEnergyInfo(SystemClock.elapsedRealtime(), mStackReportedState,
                    mTxTimeTotalMs, mRxTimeTotalMs, mIdleTimeTotalMs, mEnergyUsedTotalVoltAmpSecMicro);
                    mTxTimeTotalMs, mRxTimeTotalMs, mIdleTimeTotalMs,
                    mEnergyUsedTotalVoltAmpSecMicro);

        // Count the number of entries that have byte counts > 0
        int arrayLen = 0;
        for (int i = 0; i < mUidTraffic.size(); i++) {
            final UidTraffic traffic = mUidTraffic.valueAt(i);
            if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) {
                arrayLen++;
            }
        }

        // Copy the traffic objects whose byte counts are > 0 and reset the originals.
        final UidTraffic[] result = arrayLen > 0 ? new UidTraffic[arrayLen] : null;
        int putIdx = 0;
        for (int i = 0; i < mUidTraffic.size(); i++) {
            final UidTraffic traffic = mUidTraffic.valueAt(i);
            if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) {
                result[putIdx++] = traffic.clone();
                traffic.setRxBytes(0);
                traffic.setTxBytes(0);
            }
        }

        info.setUidTraffic(result);

        // Read on clear values; a record of data is created with
        // timstamp and new samples are collected until read again
        mStackReportedState = 0;
@@ -2058,8 +2087,8 @@ public class AdapterService extends Service {
        return true;
    }

    private void energyInfoCallback (int status, int ctrl_state,
        long tx_time, long rx_time, long idle_time, long energy_used)
    private void energyInfoCallback(int status, int ctrl_state, long tx_time, long rx_time,
                                    long idle_time, long energy_used, UidTraffic[] data)
            throws RemoteException {
        if (ctrl_state >= BluetoothActivityEnergyInfo.BT_STACK_STATE_INVALID &&
                ctrl_state <= BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_IDLE) {
@@ -2075,12 +2104,23 @@ public class AdapterService extends Service {
                    + mIdleTimeTotalMs * getIdleCurrentMa()) * getOperatingVolt());
            }
            mEnergyUsedTotalVoltAmpSecMicro += energy_used;

            for (UidTraffic traffic : data) {
                UidTraffic existingTraffic = mUidTraffic.get(traffic.getUid());
                if (existingTraffic == null) {
                    mUidTraffic.put(traffic.getUid(), traffic);
                } else {
                    existingTraffic.addRxBytes(traffic.getRxBytes());
                    existingTraffic.addTxBytes(traffic.getTxBytes());
                }
            }
        }

        debugLog("energyInfoCallback() status = " + status +
            "tx_time = " + tx_time + "rx_time = " + rx_time +
            "idle_time = " + idle_time + "energy_used = " + energy_used +
            "ctrl_state = " + ctrl_state);
            "ctrl_state = " + ctrl_state +
            "traffic = " + Arrays.toString(data));
    }

    private int getIdleCurrentMa() {
@@ -2181,9 +2221,9 @@ public class AdapterService extends Service {
    private native int readEnergyInfo();
    // TODO(BT) move this to ../btsock dir
    private native int connectSocketNative(byte[] address, int type,
                                           byte[] uuid, int port, int flag);
                                           byte[] uuid, int port, int flag, int callingUid);
    private native int createSocketChannelNative(int type, String serviceName,
                                                 byte[] uuid, int port, int flag);
                                                 byte[] uuid, int port, int flag, int callingUid);

    /*package*/ native boolean configHciSnoopLogNative(boolean enable);
    /*package*/ native boolean factoryResetNative();