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

Commit 16c99130 authored by Jack He's avatar Jack He
Browse files

Metrics: Dump Java and native metrics together

* Both Java and native metrics are dumped when calling
  "dumpsys bluetooth_manager --proto-bin".
* "dumpsys bluetooth_manager --proto-java-bin" will always dump an empty
  protobuf after this change.
* Native metrics is dumped directly to Java layer as a byte array that can be
  directly merged to Java BluetoothLog.
* Native layer initially dumps metrics as std::string. The content of
  std::string is copied to Java layer as byte array

Bug: 33693818
Test: adb shell dumpsys bluetooth_manager --proto-bin
      SL4A metrics tests: BtMetricsTest, BtFunhausMetricsTest
Change-Id: I89d8f283f5d9d2145f80c6878fd0896fa5e7dafb
parent 13e18be2
Loading
Loading
Loading
Loading
+15 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,7 @@
#include <sys/prctl.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/stat.h>


#include <hardware/bluetooth.h>
#include <mutex>
#include <mutex>


using base::StringPrintf;
using base::StringPrintf;
@@ -1172,6 +1173,19 @@ static void dumpNative(JNIEnv* env, jobject obj, jobject fdObj,
  delete[] argObjs;
  delete[] argObjs;
}
}


static jbyteArray dumpMetricsNative(JNIEnv* env, jobject obj) {
  ALOGI("%s", __func__);
  if (!sBluetoothInterface) return env->NewByteArray(0);

  std::string output;
  sBluetoothInterface->dumpMetrics(&output);
  jsize output_size = output.size() * sizeof(char);
  jbyteArray output_bytes = env->NewByteArray(output_size);
  env->SetByteArrayRegion(output_bytes, 0, output_size,
                          (const jbyte*)output.data());
  return output_bytes;
}

static jboolean factoryResetNative(JNIEnv* env, jobject obj) {
static jboolean factoryResetNative(JNIEnv* env, jobject obj) {
  ALOGV("%s", __func__);
  ALOGV("%s", __func__);
  if (!sBluetoothInterface) return JNI_FALSE;
  if (!sBluetoothInterface) return JNI_FALSE;
@@ -1231,6 +1245,7 @@ static JNINativeMethod sMethods[] = {
    {"readEnergyInfo", "()I", (void*)readEnergyInfo},
    {"readEnergyInfo", "()I", (void*)readEnergyInfo},
    {"dumpNative", "(Ljava/io/FileDescriptor;[Ljava/lang/String;)V",
    {"dumpNative", "(Ljava/io/FileDescriptor;[Ljava/lang/String;)V",
     (void*)dumpNative},
     (void*)dumpNative},
    {"dumpMetricsNative", "()[B", (void*)dumpMetricsNative},
    {"factoryResetNative", "()Z", (void*)factoryResetNative},
    {"factoryResetNative", "()Z", (void*)factoryResetNative},
    {"interopDatabaseClearNative", "()V", (void*)interopDatabaseClearNative},
    {"interopDatabaseClearNative", "()V", (void*)interopDatabaseClearNative},
    {"interopDatabaseAddNative", "(I[BI)V", (void*)interopDatabaseAddNative}};
    {"interopDatabaseAddNative", "(I[BI)V", (void*)interopDatabaseAddNative}};
+36 −17
Original line number Original line Diff line number Diff line
@@ -69,11 +69,12 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.app.IBatteryStats;


import com.google.protobuf.micro.InvalidProtocolBufferMicroException;

import java.io.FileDescriptor;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashMap;
@@ -1639,6 +1640,7 @@ public class AdapterService extends Service {
                return;
                return;
            }
            }
            service.dump(fd, writer, args);
            service.dump(fd, writer, args);
            writer.close();
        }
        }
    }
    }


@@ -2491,10 +2493,18 @@ public class AdapterService extends Service {


        verboseLog("dumpsys arguments, check for protobuf output: " + TextUtils.join(" ", args));
        verboseLog("dumpsys arguments, check for protobuf output: " + TextUtils.join(" ", args));
        if (args[0].startsWith("--proto")) {
        if (args[0].startsWith("--proto")) {
            if (args[0].equals("--proto-java-bin")) {
            if (args[0].equals("--proto-bin")) {
                dumpJava(fd);
                dumpMetrics(fd);
            } else {
            } else if (args[0].equals("--proto-java-bin")) {
                dumpNative(fd, args);
                // TODO: Remove once --proto-java-bin is no longer used
                BluetoothProto.BluetoothLog metrics = new BluetoothProto.BluetoothLog();
                byte[] metricsBytes = Base64.encode(metrics.toByteArray(), Base64.DEFAULT);
                Log.w(TAG, "proto-java-bin dump, empty metrics size is " + metricsBytes.length);
                try (FileOutputStream protoOut = new FileOutputStream(fd)) {
                    protoOut.write(metricsBytes);
                } catch (IOException e) {
                    errorLog("Unable to write Java protobuf to file descriptor.");
                }
            }
            }
            return;
            return;
        }
        }
@@ -2520,21 +2530,28 @@ public class AdapterService extends Service {
        dumpNative(fd, args);
        dumpNative(fd, args);
    }
    }


    private void dumpJava(FileDescriptor fd) {
    private void dumpMetrics(FileDescriptor fd) {
        BluetoothProto.BluetoothLog log = new BluetoothProto.BluetoothLog();
        BluetoothProto.BluetoothLog metrics = new BluetoothProto.BluetoothLog();
        log.setNumBondedDevices(getBondedDevices().length);
        metrics.setNumBondedDevices(getBondedDevices().length);

        for (ProfileService profile : mProfiles) {
        for (ProfileService profile : mProfiles) {
            profile.dumpProto(log);
            profile.dumpProto(metrics);
        }
        }

        byte[] nativeMetricsBytes = dumpMetricsNative();
        debugLog("dumpMetrics: native metrics size is " + nativeMetricsBytes.length);
        if (nativeMetricsBytes.length > 0) {
            try {
            try {
            FileOutputStream protoOut = new FileOutputStream(fd);
                metrics.mergeFrom(nativeMetricsBytes);
            String protoOutString = Base64.encodeToString(log.toByteArray(), Base64.DEFAULT);
            } catch (InvalidProtocolBufferMicroException ex) {
            protoOut.write(protoOutString.getBytes(StandardCharsets.UTF_8));
                Log.w(TAG, "dumpMetrics: problem parsing metrics protobuf, " + ex.getMessage());
            protoOut.close();
                return;
            }
        }
        byte[] metricsBytes = Base64.encode(metrics.toByteArray(), Base64.DEFAULT);
        debugLog("dumpMetrics: combined metrics size is " + metricsBytes.length);
        try (FileOutputStream protoOut = new FileOutputStream(fd)) {
            protoOut.write(metricsBytes);
        } catch (IOException e) {
        } catch (IOException e) {
            errorLog("Unable to write Java protobuf to file descriptor.");
            errorLog("dumpMetrics: error writing combined protobuf to fd, " + e.getMessage());
        }
        }
    }
    }


@@ -2641,6 +2658,8 @@ public class AdapterService extends Service {


    private native void dumpNative(FileDescriptor fd, String[] arguments);
    private native void dumpNative(FileDescriptor fd, String[] arguments);


    private native byte[] dumpMetricsNative();

    private native void interopDatabaseClearNative();
    private native void interopDatabaseClearNative();


    private native void interopDatabaseAddNative(int feature, byte[] address, int length);
    private native void interopDatabaseAddNative(int feature, byte[] address, int length);