blob: fb55e0098fe441477d37b157c815488305fe730d [file]
/*
* Copyright (C) 2025 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.
*/
#include "src/android_sdk/jni/dev_perfetto_sdk_PerfettoTrackEventExtra.h"
#include <jni.h>
#include "src/android_sdk/jni/macros.h"
#include "src/android_sdk/nativehelper/JNIHelp.h"
#include "src/android_sdk/nativehelper/scoped_utf_chars.h"
#include "src/android_sdk/perfetto_sdk_for_jni/tracing_sdk.h"
#include <algorithm>
#include <list>
#include <utility>
namespace perfetto {
namespace jni {
template <typename T>
inline static T* toPointer(jlong ptr) {
return reinterpret_cast<T*>(static_cast<uintptr_t>(ptr));
}
template <typename T>
inline static jlong toJLong(T* ptr) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(ptr));
}
/**
* @brief A thread-safe utility class for converting Java UTF-16 strings to
* ASCII in JNI environment.
*
* StringBuffer provides efficient conversion of Java strings to ASCII with
* optimized memory handling. It uses a two-tiered buffering strategy:
* 1. A fast path using pre-allocated thread-local buffers for strings up to 128
* characters
* 2. A fallback path using dynamic allocation for longer strings
*
* Non-ASCII characters (>255) are replaced with '?' during conversion. The
* class maintains thread safety through thread-local storage and provides
* zero-copy string views for optimal performance.
*
* Memory Management:
* - Uses fixed-size thread-local buffers for both UTF-16 and ASCII characters
* - Overflow strings are stored in a thread-local list to maintain valid string
* views
* - Avoids unnecessary allocations in the common case of small strings
*
* Usage example:
* @code
* JNIEnv* env = ...;
* jstring java_string = ...;
* std::string_view ascii = StringBuffer::utf16_to_ascii(env, java_string);
* // Use the ASCII string...
* StringBuffer::reset(); // Clean up when done
* @endcode
*
* Thread Safety: All methods are thread-safe due to thread-local storage.
*/
class StringBuffer {
private:
static constexpr size_t BASE_SIZE = 128;
// Temporarily stores the UTF-16 characters retrieved from the Java
// string before they are converted to ASCII.
static thread_local inline char char_buffer[BASE_SIZE];
// For fast-path conversions when the resulting ASCII string fits within
// the pre-allocated space. All ascii strings in a trace event will be stored
// here until emitted.
static thread_local inline jchar jchar_buffer[BASE_SIZE];
// When the fast-path conversion is not possible (because char_buffer
// doesn't have enough space), the converted ASCII string is stored
// in this list. We use list here to avoid moving the strings on resize
// with vector. This way, we can give out string_views from the stored
// strings. The additional overhead from list node allocations is fine cos we
// are already in an extremely unlikely path here and there are other bigger
// problems if here.
static thread_local inline std::list<std::string> overflow_strings;
// current offset into the char_buffer.
static thread_local inline size_t current_offset{0};
// This allows us avoid touching the overflow_strings directly in the fast
// path. Touching it causes some thread local init routine to run which shows
// up in profiles.
static thread_local inline bool is_overflow_strings_empty = true;
static void copy_utf16_to_ascii(const jchar* src,
size_t len,
char* dst,
JNIEnv* env,
jstring str) {
std::transform(src, src + len, dst, [](jchar c) {
return (c <= 0xFF) ? static_cast<char>(c) : '?';
});
if (src != jchar_buffer) {
// We hit the slow path to populate src, so we have to release.
env->ReleaseStringCritical(str, src);
}
}
public:
static void reset() {
if (!is_overflow_strings_empty) {
overflow_strings.clear();
is_overflow_strings_empty = true;
}
current_offset = 0;
}
// Converts a Java string (jstring) to an ASCII string_view. Characters
// outside the ASCII range (0-255) are replaced with '?'.
//
// @param env The JNI environment.
// @param val The Java string to convert.
// @return A string_view representing the ASCII version of the string.
// Returns an empty string_view if the input is null or empty.
static std::string_view utf16_to_ascii(JNIEnv* env, jstring val) {
if (!val)
return "";
const jsize len = env->GetStringLength(val);
if (len == 0)
return "";
const jchar* temp_buffer;
// Fast path: Enough space in jchar_buffer
if (static_cast<size_t>(len) <= BASE_SIZE) {
env->GetStringRegion(val, 0, len, jchar_buffer);
temp_buffer = jchar_buffer;
} else {
// Slow path: Fallback to asking ART for the string which will likely
// allocate and return a copy.
temp_buffer = env->GetStringCritical(val, nullptr);
}
const size_t next_offset = current_offset + len + 1;
// Fast path: Enough space in char_buffer
if (BASE_SIZE > next_offset) {
copy_utf16_to_ascii(temp_buffer, len, char_buffer + current_offset, env,
val);
char_buffer[current_offset + len] = '\0';
auto res = std::string_view(char_buffer + current_offset, len);
current_offset = next_offset;
return res;
} else {
// Slow path: Not enough space in char_buffer. Use overflow_strings.
// This will cause a string alloc but should be very unlikely to hit.
std::string& str = overflow_strings.emplace_back(len + 1, '\0');
copy_utf16_to_ascii(temp_buffer, len, str.data(), env, val);
is_overflow_strings_empty = false;
return std::string_view(str);
}
}
};
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraArg_init(JNIEnv* env,
jclass,
jstring name) {
return toJLong(new sdk_for_jni::DebugArg(
StringBuffer::utf16_to_ascii(env, name).data()));
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraArg_delete(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(&sdk_for_jni::DebugArg::delete_arg);
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraArg_get_extra_ptr(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::DebugArg* arg = toPointer<sdk_for_jni::DebugArg>(ptr);
return toJLong(arg->get());
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraArg_set_value_int64(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr,
jlong val) {
sdk_for_jni::DebugArg* arg = toPointer<sdk_for_jni::DebugArg>(ptr);
auto& arg_int64 = arg->get()->arg_int64;
arg_int64.header.type = PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_INT64;
arg_int64.name = arg->name();
arg_int64.value = val;
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraArg_set_value_bool(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr,
jboolean val) {
sdk_for_jni::DebugArg* arg = toPointer<sdk_for_jni::DebugArg>(ptr);
auto& arg_bool = arg->get()->arg_bool;
arg_bool.header.type = PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_BOOL;
arg_bool.name = arg->name();
arg_bool.value = val;
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraArg_set_value_double(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr,
jdouble val) {
sdk_for_jni::DebugArg* arg = toPointer<sdk_for_jni::DebugArg>(ptr);
auto& arg_double = arg->get()->arg_double;
arg_double.header.type = PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_DOUBLE;
arg_double.name = arg->name();
arg_double.value = val;
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraArg_set_value_string(
JNIEnv* env,
jclass,
jlong ptr,
jstring val) {
sdk_for_jni::DebugArg* arg = toPointer<sdk_for_jni::DebugArg>(ptr);
auto& arg_string = arg->get()->arg_string;
arg_string.header.type = PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_STRING;
arg_string.name = arg->name();
arg_string.value = StringBuffer::utf16_to_ascii(env, val).data();
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraField_init(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(new sdk_for_jni::ProtoField());
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraFieldNested_init(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(new sdk_for_jni::ProtoFieldNested());
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraField_delete(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(&sdk_for_jni::ProtoField::delete_field);
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraFieldNested_delete(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(&sdk_for_jni::ProtoFieldNested::delete_field);
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraField_get_extra_ptr(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::ProtoField* field = toPointer<sdk_for_jni::ProtoField>(ptr);
return toJLong(field->get());
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraFieldNested_get_extra_ptr(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::ProtoFieldNested* field =
toPointer<sdk_for_jni::ProtoFieldNested>(ptr);
return toJLong(field->get());
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraField_set_value_int64(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr,
jlong id,
jlong val) {
sdk_for_jni::ProtoField* field = toPointer<sdk_for_jni::ProtoField>(ptr);
auto& field_varint = field->get()->field_varint;
field_varint.header.type = PERFETTO_TE_HL_PROTO_TYPE_VARINT;
field_varint.header.id = static_cast<uint32_t>(id);
field_varint.value = val;
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraField_set_value_double(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr,
jlong id,
jdouble val) {
sdk_for_jni::ProtoField* field = toPointer<sdk_for_jni::ProtoField>(ptr);
auto& field_double = field->get()->field_double;
field_double.header.type = PERFETTO_TE_HL_PROTO_TYPE_DOUBLE;
field_double.header.id = static_cast<uint32_t>(id);
field_double.value = val;
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraField_set_value_string(
JNIEnv* env,
jclass,
jlong ptr,
jlong id,
jstring val) {
sdk_for_jni::ProtoField* field = toPointer<sdk_for_jni::ProtoField>(ptr);
auto& field_cstr = field->get()->field_cstr;
field_cstr.header.type = PERFETTO_TE_HL_PROTO_TYPE_CSTR;
field_cstr.header.id = static_cast<uint32_t>(id);
field_cstr.str = StringBuffer::utf16_to_ascii(env, val).data();
}
static void
dev_perfetto_sdk_PerfettoTrackEventExtraField_set_value_with_interning(
JNIEnv* env,
jclass,
jlong ptr,
jlong id,
jstring val,
jlong interned_type_id) {
sdk_for_jni::ProtoField* field = toPointer<sdk_for_jni::ProtoField>(ptr);
auto& field_cstr = field->get()->field_cstr_interned;
field_cstr.header.type = PERFETTO_TE_HL_PROTO_TYPE_CSTR_INTERNED;
field_cstr.header.id = static_cast<uint32_t>(id);
field_cstr.str = StringBuffer::utf16_to_ascii(env, val).data();
field_cstr.interned_type_id = static_cast<uint32_t>(interned_type_id);
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraFieldNested_add_field(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong field_ptr,
jlong arg_ptr) {
sdk_for_jni::ProtoFieldNested* field =
toPointer<sdk_for_jni::ProtoFieldNested>(field_ptr);
field->add_field(toPointer<PerfettoTeHlProtoField>(arg_ptr));
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraFieldNested_set_id(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr,
jlong id) {
sdk_for_jni::ProtoFieldNested* field =
toPointer<sdk_for_jni::ProtoFieldNested>(ptr);
field->set_id(id);
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraFlow_init(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(new sdk_for_jni::Flow());
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraFlow_set_process_flow(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr,
jlong id) {
sdk_for_jni::Flow* flow = toPointer<sdk_for_jni::Flow>(ptr);
flow->set_process_flow(id);
}
static void
dev_perfetto_sdk_PerfettoTrackEventExtraFlow_set_process_terminating_flow(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr,
jlong id) {
sdk_for_jni::Flow* flow = toPointer<sdk_for_jni::Flow>(ptr);
flow->set_process_terminating_flow(id);
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraFlow_delete(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(&sdk_for_jni::Flow::delete_flow);
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraFlow_get_extra_ptr(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::Flow* flow = toPointer<sdk_for_jni::Flow>(ptr);
return toJLong(flow->get());
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraNamedTrack_init(
JNIEnv* env,
jclass,
jlong id,
jstring name,
jlong parent_uuid,
jboolean is_name_static) {
return toJLong(new sdk_for_jni::NamedTrack(
id, parent_uuid, StringBuffer::utf16_to_ascii(env, name).data(),
is_name_static));
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraNamedTrack_delete(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(&sdk_for_jni::NamedTrack::delete_track);
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraNamedTrack_get_extra_ptr(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::NamedTrack* track = toPointer<sdk_for_jni::NamedTrack>(ptr);
return toJLong(track->get());
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraNestedTracks_init(
JNIEnv* env,
jclass,
jint root_type,
jobjectArray names,
jlongArray ids,
jintArray sibling_order_ranks,
jintArray child_orderings,
jintArray sibling_merge_behaviors,
jobjectArray merge_keys_str,
jlongArray merge_keys_int) {
const jsize num_names = env->GetArrayLength(names);
// All the arrays are built in lockstep by PerfettoTrack, so the lengths
// should match. Tracing must never crash the caller, so on a mismatch just
// log and use the shortest length rather than over-reading.
jsize n = num_names;
const jsize lengths[] = {env->GetArrayLength(ids),
env->GetArrayLength(sibling_order_ranks),
env->GetArrayLength(child_orderings),
env->GetArrayLength(sibling_merge_behaviors),
env->GetArrayLength(merge_keys_str),
env->GetArrayLength(merge_keys_int)};
for (jsize length : lengths) {
if (length != num_names) {
__android_log_print(ANDROID_LOG_ERROR, "PerfettoJNI",
"nested track parallel array length mismatch "
"(names %d vs %d)",
num_names, length);
n = n < length ? n : length;
}
}
// Bulk-copy the primitive arrays, then assemble one NestedLevel per level.
// The name and merge key (object arrays) have no region accessor, so they are
// read per element.
std::vector<uint64_t> ids_vec(static_cast<size_t>(n));
env->GetLongArrayRegion(ids, 0, n, reinterpret_cast<jlong*>(ids_vec.data()));
std::vector<int32_t> ranks_vec(static_cast<size_t>(n));
env->GetIntArrayRegion(sibling_order_ranks, 0, n,
reinterpret_cast<jint*>(ranks_vec.data()));
std::vector<uint32_t> orderings_vec(static_cast<size_t>(n));
env->GetIntArrayRegion(child_orderings, 0, n,
reinterpret_cast<jint*>(orderings_vec.data()));
std::vector<uint32_t> merge_behaviors_vec(static_cast<size_t>(n));
env->GetIntArrayRegion(sibling_merge_behaviors, 0, n,
reinterpret_cast<jint*>(merge_behaviors_vec.data()));
std::vector<uint64_t> merge_keys_int_vec(static_cast<size_t>(n));
env->GetLongArrayRegion(merge_keys_int, 0, n,
reinterpret_cast<jlong*>(merge_keys_int_vec.data()));
std::vector<sdk_for_jni::NestedLevel> levels(static_cast<size_t>(n));
for (jsize i = 0; i < n; i++) {
sdk_for_jni::NestedLevel& level = levels[static_cast<size_t>(i)];
jstring s = static_cast<jstring>(env->GetObjectArrayElement(names, i));
level.name = StringBuffer::utf16_to_ascii(env, s);
env->DeleteLocalRef(s);
level.id = ids_vec[static_cast<size_t>(i)];
level.sibling_order_rank = ranks_vec[static_cast<size_t>(i)];
level.child_ordering = orderings_vec[static_cast<size_t>(i)];
level.sibling_merge_behavior = merge_behaviors_vec[static_cast<size_t>(i)];
jstring key =
static_cast<jstring>(env->GetObjectArrayElement(merge_keys_str, i));
if (key == nullptr) {
level.sibling_merge_key_str = std::nullopt;
} else {
level.sibling_merge_key_str = StringBuffer::utf16_to_ascii(env, key);
env->DeleteLocalRef(key);
}
level.sibling_merge_key_int = merge_keys_int_vec[static_cast<size_t>(i)];
}
return toJLong(new sdk_for_jni::NestedTracks(
static_cast<sdk_for_jni::RootType>(root_type), std::move(levels)));
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraNestedTracks_delete(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(&sdk_for_jni::NestedTracks::delete_track);
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraNestedTracks_get_extra_ptr(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::NestedTracks* track = toPointer<sdk_for_jni::NestedTracks>(ptr);
return toJLong(track->get());
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraCounterTrack_init(
JNIEnv* env,
jclass,
jstring name,
jlong parent_uuid,
jboolean is_name_static) {
return toJLong(new sdk_for_jni::RegisteredTrack(
// id disambiguates same-named named-tracks; unused for counter/state.
/*id=*/0, parent_uuid, StringBuffer::utf16_to_ascii(env, name).data(),
/*is_counter=*/true, is_name_static, /*is_state=*/false));
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraCounterTrack_delete(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(&sdk_for_jni::RegisteredTrack::delete_track);
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraCounterTrack_get_extra_ptr(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::RegisteredTrack* track =
toPointer<sdk_for_jni::RegisteredTrack>(ptr);
return toJLong(track->get());
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraStateTrack_init(
JNIEnv* env,
jclass,
jstring name,
jlong parent_uuid,
jboolean is_name_static) {
return toJLong(new sdk_for_jni::RegisteredTrack(
// id disambiguates same-named named-tracks; unused for counter/state.
/*id=*/0, parent_uuid, StringBuffer::utf16_to_ascii(env, name).data(),
/*is_counter=*/false, is_name_static, /*is_state=*/true));
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraStateTrack_delete(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(&sdk_for_jni::RegisteredTrack::delete_track);
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraStateTrack_get_extra_ptr(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::RegisteredTrack* track =
toPointer<sdk_for_jni::RegisteredTrack>(ptr);
return toJLong(track->get());
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraCorrelationId_init(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(new sdk_for_jni::CorrelationId());
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraCorrelationId_delete(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(&sdk_for_jni::CorrelationId::delete_correlation_id);
}
static jlong
dev_perfetto_sdk_PerfettoTrackEventExtraCorrelationId_get_extra_ptr(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::CorrelationId* correlation_id =
toPointer<sdk_for_jni::CorrelationId>(ptr);
return toJLong(correlation_id->get());
}
static void
dev_perfetto_sdk_PerfettoTrackEventExtraCorrelationId_set_value_int64(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr,
jlong val) {
sdk_for_jni::CorrelationId* correlation_id =
toPointer<sdk_for_jni::CorrelationId>(ptr);
auto& id = correlation_id->get()->correlation_id;
id.header.type = PERFETTO_TE_HL_EXTRA_TYPE_CORRELATION_ID;
id.id = static_cast<uint64_t>(val);
}
static void
dev_perfetto_sdk_PerfettoTrackEventExtraCorrelationId_set_value_string(
JNIEnv* env,
jclass,
jlong ptr,
jstring val) {
sdk_for_jni::CorrelationId* correlation_id =
toPointer<sdk_for_jni::CorrelationId>(ptr);
auto& id_str = correlation_id->get()->correlation_id_str;
id_str.header.type = PERFETTO_TE_HL_EXTRA_TYPE_CORRELATION_ID_STR;
id_str.str = StringBuffer::utf16_to_ascii(env, val).data();
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraCounter_init(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(new sdk_for_jni::Counter());
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraCounter_delete(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(&sdk_for_jni::Counter::delete_counter);
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraCounter_get_extra_ptr(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::Counter* counter = toPointer<sdk_for_jni::Counter>(ptr);
return toJLong(counter->get());
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraCounter_set_value_int64(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr,
jlong val) {
sdk_for_jni::Counter* counter = toPointer<sdk_for_jni::Counter>(ptr);
auto& counter_int64 = counter->get()->counter_int64;
counter_int64.header.type = PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_INT64;
counter_int64.value = val;
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraCounter_set_value_double(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr,
jdouble val) {
sdk_for_jni::Counter* counter = toPointer<sdk_for_jni::Counter>(ptr);
auto& counter_double = counter->get()->counter_double;
counter_double.header.type = PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_DOUBLE;
counter_double.value = val;
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtra_init(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(new sdk_for_jni::Extra());
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtra_delete(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(&sdk_for_jni::Extra::delete_extra);
}
static void dev_perfetto_sdk_PerfettoTrackEventExtra_add_arg(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong extra_ptr,
jlong arg_ptr) {
sdk_for_jni::Extra* extra = toPointer<sdk_for_jni::Extra>(extra_ptr);
extra->push_extra(toPointer<PerfettoTeHlExtra>(arg_ptr));
}
static void dev_perfetto_sdk_PerfettoTrackEventExtra_clear_args(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::Extra* extra = toPointer<sdk_for_jni::Extra>(ptr);
extra->clear_extras();
}
static void dev_perfetto_sdk_PerfettoTrackEventExtra_emit(JNIEnv* env,
jclass,
jint type,
jlong cat_ptr,
jstring name,
jlong extra_ptr) {
sdk_for_jni::Category* category = toPointer<sdk_for_jni::Category>(cat_ptr);
trace_event(type, category->get(),
StringBuffer::utf16_to_ascii(env, name).data(),
toPointer<sdk_for_jni::Extra>(extra_ptr));
StringBuffer::reset();
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraProto_init(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(new sdk_for_jni::Proto());
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraProto_delete(
PERFETTO_JNI_HOST_PARAMS) {
return toJLong(&sdk_for_jni::Proto::delete_proto);
}
static jlong dev_perfetto_sdk_PerfettoTrackEventExtraProto_get_extra_ptr(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::Proto* proto = toPointer<sdk_for_jni::Proto>(ptr);
return toJLong(proto->get());
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraProto_add_field(
PERFETTO_JNI_HOST_PARAMS_COMMA long proto_ptr,
jlong arg_ptr) {
sdk_for_jni::Proto* proto = toPointer<sdk_for_jni::Proto>(proto_ptr);
proto->add_field(toPointer<PerfettoTeHlProtoField>(arg_ptr));
}
static void dev_perfetto_sdk_PerfettoTrackEventExtraProto_clear_fields(
PERFETTO_JNI_HOST_PARAMS_COMMA jlong ptr) {
sdk_for_jni::Proto* proto = toPointer<sdk_for_jni::Proto>(ptr);
proto->clear_fields();
}
static const JNINativeMethod gExtraMethods[] = {
{"native_init", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtra_init},
{"native_delete", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtra_delete},
{"native_add_arg", "(JJ)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtra_add_arg},
{"native_clear_args", "(J)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtra_clear_args},
{"native_emit", "(IJLjava/lang/String;J)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtra_emit}};
static const JNINativeMethod gProtoMethods[] = {
{"native_init", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraProto_init},
{"native_delete", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraProto_delete},
{"native_get_extra_ptr", "(J)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraProto_get_extra_ptr},
{"native_add_field", "(JJ)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraProto_add_field},
{"native_clear_fields", "(J)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraProto_clear_fields}};
static const JNINativeMethod gArgMethods[] = {
{"native_init", "(Ljava/lang/String;)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraArg_init},
{"native_delete", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraArg_delete},
{"native_get_extra_ptr", "(J)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraArg_get_extra_ptr},
{"native_set_value_int64", "(JJ)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraArg_set_value_int64},
{"native_set_value_bool", "(JZ)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraArg_set_value_bool},
{"native_set_value_double", "(JD)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraArg_set_value_double},
{"native_set_value_string", "(JLjava/lang/String;)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraArg_set_value_string},
};
static const JNINativeMethod gFieldMethods[] = {
{"native_init", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraField_init},
{"native_delete", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraField_delete},
{"native_get_extra_ptr", "(J)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraField_get_extra_ptr},
{"native_set_value_int64", "(JJJ)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraField_set_value_int64},
{"native_set_value_double", "(JJD)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraField_set_value_double},
{"native_set_value_string", "(JJLjava/lang/String;)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraField_set_value_string},
{"native_set_value_with_interning", "(JJLjava/lang/String;J)V",
(void*)
dev_perfetto_sdk_PerfettoTrackEventExtraField_set_value_with_interning},
};
static const JNINativeMethod gFieldNestedMethods[] = {
{"native_init", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraFieldNested_init},
{"native_delete", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraFieldNested_delete},
{"native_get_extra_ptr", "(J)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraFieldNested_get_extra_ptr},
{"native_add_field", "(JJ)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraFieldNested_add_field},
{"native_set_id", "(JJ)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraFieldNested_set_id}};
static const JNINativeMethod gFlowMethods[] = {
{"native_init", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraFlow_init},
{"native_delete", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraFlow_delete},
{"native_set_process_flow", "(JJ)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraFlow_set_process_flow},
{"native_set_process_terminating_flow", "(JJ)V",
(void*)
dev_perfetto_sdk_PerfettoTrackEventExtraFlow_set_process_terminating_flow},
{"native_get_extra_ptr", "(J)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraFlow_get_extra_ptr},
};
static const JNINativeMethod gNamedTrackMethods[] = {
{"native_init", "(JLjava/lang/String;JZ)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraNamedTrack_init},
{"native_delete", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraNamedTrack_delete},
{"native_get_extra_ptr", "(J)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraNamedTrack_get_extra_ptr},
};
static const JNINativeMethod gNestedTracksMethods[] = {
{"native_init", "(I[Ljava/lang/String;[J[I[I[I[Ljava/lang/String;[J)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraNestedTracks_init},
{"native_delete", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraNestedTracks_delete},
{"native_get_extra_ptr", "(J)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraNestedTracks_get_extra_ptr},
};
static const JNINativeMethod gCounterTrackMethods[] = {
{"native_init", "(Ljava/lang/String;JZ)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraCounterTrack_init},
{"native_delete", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraCounterTrack_delete},
{"native_get_extra_ptr", "(J)J",
(void*)
dev_perfetto_sdk_PerfettoTrackEventExtraCounterTrack_get_extra_ptr}};
static const JNINativeMethod gStateTrackMethods[] = {
{"native_init", "(Ljava/lang/String;JZ)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraStateTrack_init},
{"native_delete", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraStateTrack_delete},
{"native_get_extra_ptr", "(J)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraStateTrack_get_extra_ptr}};
static const JNINativeMethod gCorrelationIdMethods[] = {
{"native_init", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraCorrelationId_init},
{"native_delete", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraCorrelationId_delete},
{"native_get_extra_ptr", "(J)J",
(void*)
dev_perfetto_sdk_PerfettoTrackEventExtraCorrelationId_get_extra_ptr},
{"native_set_value_int64", "(JJ)V",
(void*)
dev_perfetto_sdk_PerfettoTrackEventExtraCorrelationId_set_value_int64},
{"native_set_value_string", "(JLjava/lang/String;)V",
(void*)
dev_perfetto_sdk_PerfettoTrackEventExtraCorrelationId_set_value_string}};
static const JNINativeMethod gCounterMethods[] = {
{"native_init", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraCounter_init},
{"native_delete", "()J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraCounter_delete},
{"native_get_extra_ptr", "(J)J",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraCounter_get_extra_ptr},
{"native_set_value_int64", "(JJ)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraCounter_set_value_int64},
{"native_set_value_double", "(JD)V",
(void*)dev_perfetto_sdk_PerfettoTrackEventExtraCounter_set_value_double}};
int register_dev_perfetto_sdk_PerfettoTrackEventExtra(JNIEnv* env) {
int res = jniRegisterNativeMethods(
env,
TO_MAYBE_JAR_JAR_CLASS_NAME(
"dev/perfetto/sdk/PerfettoTrackEventExtra$Arg"),
gArgMethods, NELEM(gArgMethods));
LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register arg native methods.");
res = jniRegisterNativeMethods(
env,
TO_MAYBE_JAR_JAR_CLASS_NAME(
"dev/perfetto/sdk/PerfettoTrackEventExtra$Field"),
gFieldMethods, NELEM(gFieldMethods));
LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register field native methods.");
res = jniRegisterNativeMethods(
env,
TO_MAYBE_JAR_JAR_CLASS_NAME(
"dev/perfetto/sdk/PerfettoTrackEventExtra$FieldNested"),
gFieldNestedMethods, NELEM(gFieldNestedMethods));
LOG_ALWAYS_FATAL_IF(res < 0,
"Unable to register field nested native methods.");
res = jniRegisterNativeMethods(
env,
TO_MAYBE_JAR_JAR_CLASS_NAME("dev/perfetto/sdk/PerfettoTrackEventExtra"),
gExtraMethods, NELEM(gExtraMethods));
LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register extra native methods.");
res = jniRegisterNativeMethods(
env,
TO_MAYBE_JAR_JAR_CLASS_NAME(
"dev/perfetto/sdk/PerfettoTrackEventExtra$Proto"),
gProtoMethods, NELEM(gProtoMethods));
LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register proto native methods.");
res = jniRegisterNativeMethods(
env,
TO_MAYBE_JAR_JAR_CLASS_NAME(
"dev/perfetto/sdk/PerfettoTrackEventExtra$Flow"),
gFlowMethods, NELEM(gFlowMethods));
LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register flow native methods.");
res = jniRegisterNativeMethods(
env,
TO_MAYBE_JAR_JAR_CLASS_NAME(
"dev/perfetto/sdk/PerfettoTrackEventExtra$NamedTrack"),
gNamedTrackMethods, NELEM(gNamedTrackMethods));
LOG_ALWAYS_FATAL_IF(res < 0,
"Unable to register named track native methods.");
res = jniRegisterNativeMethods(
env,
TO_MAYBE_JAR_JAR_CLASS_NAME(
"dev/perfetto/sdk/PerfettoTrackEventExtra$NestedTracks"),
gNestedTracksMethods, NELEM(gNestedTracksMethods));
LOG_ALWAYS_FATAL_IF(res < 0,
"Unable to register nested tracks native methods.");
res = jniRegisterNativeMethods(
env,
TO_MAYBE_JAR_JAR_CLASS_NAME(
"dev/perfetto/sdk/PerfettoTrackEventExtra$CounterTrack"),
gCounterTrackMethods, NELEM(gCounterTrackMethods));
LOG_ALWAYS_FATAL_IF(res < 0,
"Unable to register counter track native methods.");
res = jniRegisterNativeMethods(
env,
TO_MAYBE_JAR_JAR_CLASS_NAME(
"dev/perfetto/sdk/PerfettoTrackEventExtra$StateTrack"),
gStateTrackMethods, NELEM(gStateTrackMethods));
LOG_ALWAYS_FATAL_IF(res < 0,
"Unable to register state track native methods.");
res = jniRegisterNativeMethods(
env,
TO_MAYBE_JAR_JAR_CLASS_NAME(
"dev/perfetto/sdk/PerfettoTrackEventExtra$Counter"),
gCounterMethods, NELEM(gCounterMethods));
LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register counter native methods.");
res = jniRegisterNativeMethods(
env,
TO_MAYBE_JAR_JAR_CLASS_NAME(
"dev/perfetto/sdk/PerfettoTrackEventExtra$CorrelationId"),
gCorrelationIdMethods, NELEM(gCorrelationIdMethods));
LOG_ALWAYS_FATAL_IF(res < 0,
"Unable to register correlation id native methods.");
return 0;
}
} // namespace jni
} // namespace perfetto