Index: base/android/early_trace_event.cc |
diff --git a/base/android/early_trace_event.cc b/base/android/early_trace_event.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d354a3aeb9b2efff0929d495f3b0ea5e798e456a |
--- /dev/null |
+++ b/base/android/early_trace_event.cc |
@@ -0,0 +1,123 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/android/early_trace_event.h" |
+ |
+#include <jni.h> |
+ |
+#include <string> |
+#include <vector> |
+ |
+#include "base/android/jni_array.h" |
+#include "base/basictypes.h" |
+#include "base/time/time.h" |
+#include "base/trace_event/trace_event.h" |
+#include "jni/EarlyTraceEvent_jni.h" |
+ |
+namespace base { |
+namespace android { |
+namespace { |
+ |
+int64_t MillisecondsToMicroseconds(int64_t value) { |
+ return value * 1000; |
+} |
+ |
+// Converts events recorded on the Java side in milliseconds (since boot time) |
+// to microsecond-precision TimeTicks (as TraceLog expects). |
+TimeTicks ConvertJavaTimeSinceBoot(int64_t time_since_boot_msec, |
+ int64_t time_offset_msec) { |
+ return TimeTicks::FromInternalValue( |
+ MillisecondsToMicroseconds(time_since_boot_msec - time_offset_msec)); |
+} |
+ |
+TimeTicks ConvertJavaThreadTime(int64_t time_msec) { |
+ return TimeTicks::FromInternalValue(MillisecondsToMicroseconds(time_msec)); |
+} |
+ |
+} // namespace |
+ |
+bool RegisterEarlyTraceEvent(JNIEnv* env) { |
+ return RegisterNativesImpl(env); |
+} |
+ |
+EarlyTraceEvent::EarlyTraceEvent() {} |
+ |
+EarlyTraceEvent::~EarlyTraceEvent() {} |
+ |
+void GetAllEarlyTraceEvents(std::vector<EarlyTraceEvent>* trace_events) { |
+ JNIEnv* const env = AttachCurrentThread(); |
+ const ScopedJavaLocalRef<jobject> early_events_reader = |
+ Java_EarlyTraceEvent_getAll(env); |
+ |
+ // Convert the name string array. |
+ std::vector<std::string> names_vector; |
+ |
+ const ScopedJavaLocalRef<jobjectArray> jni_event_names = |
+ Java_EarlyTraceEventsNativeReader_readNames( |
+ env, early_events_reader.obj()); |
+ AppendJavaStringArrayToStringVector( |
+ env, jni_event_names.obj(), &names_vector); |
+ |
+ // Convert all the long arrays. |
+ std::vector<int64_t> thread_ids_vector; |
+ std::vector<int64_t> begin_times_since_boot_vector; |
+ std::vector<int64_t> begin_thread_times_vector; |
+ std::vector<int64_t> end_times_since_boot_vector; |
+ std::vector<int64_t> end_thread_times_vector; |
+ |
+ static const struct { |
+ ScopedJavaLocalRef<jlongArray> (* const jni_function)(JNIEnv*, jobject); |
+ std::vector<int64_t>* const output_vector; |
+ } long_array_descriptors[] = { |
+ { Java_EarlyTraceEventsNativeReader_readThreadIds, &thread_ids_vector }, |
+ { Java_EarlyTraceEventsNativeReader_readBeginTimesSinceBootMsec, |
+ &begin_times_since_boot_vector }, |
+ { Java_EarlyTraceEventsNativeReader_readBeginThreadTimesMsec, |
+ &begin_thread_times_vector }, |
+ { Java_EarlyTraceEventsNativeReader_readEndTimesSinceBootMsec, |
+ &end_times_since_boot_vector }, |
+ { Java_EarlyTraceEventsNativeReader_readEndThreadTimesMsec, |
+ &end_thread_times_vector }, |
+ }; |
+ |
+ for (size_t i = 0; |
+ i < sizeof(long_array_descriptors) / sizeof(long_array_descriptors[0]); |
+ ++i) { |
+ const android::ScopedJavaLocalRef<jlongArray> jni_array = |
+ long_array_descriptors[i].jni_function(env, early_events_reader.obj()); |
+ AppendJavaLongArrayToLongVector( |
+ env, jni_array.obj(), long_array_descriptors[i].output_vector); |
+ } |
+ |
+ // The Java side uses times since boot whereas TraceLog uses |
+ // TimeTicks::NowFromSystemTraceTime(). The difference between those two time |
+ // systems must be propagated to all the early trace events that were |
+ // recorded. |
+ const int64_t time_offset_msec = |
+ Java_EarlyTraceEvent_getMsecTimeSinceBoot(env) - |
+ TimeTicks::NowFromSystemTraceTime().ToInternalValue() / 1000; |
+ |
+ const size_t events_count = names_vector.size(); |
+ trace_events->reserve(events_count); |
+ |
+ for (size_t i = 0; i < events_count; ++i) { |
+ trace_events->push_back(EarlyTraceEvent()); |
+ EarlyTraceEvent* const event = &trace_events->back(); |
+ |
+ event->name.swap(names_vector[i]); |
+ event->thread_id = thread_ids_vector[i]; |
+ |
+ event->begin_timestamp = ConvertJavaTimeSinceBoot( |
+ begin_times_since_boot_vector[i], time_offset_msec); |
+ event->end_timestamp = ConvertJavaTimeSinceBoot( |
+ end_times_since_boot_vector[i], time_offset_msec); |
+ |
+ event->begin_thread_time = ConvertJavaThreadTime( |
+ begin_thread_times_vector[i]); |
+ event->end_thread_time = ConvertJavaThreadTime(end_thread_times_vector[i]); |
+ } |
+} |
+ |
+} // namespace android |
+} // namespace base |