Merge "Fix crash when recreating producer."
diff --git a/Android.bp b/Android.bp
index c6468df..f780212 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1651,6 +1651,7 @@
name: "perfetto_protos_perfetto_trace_minimal_lite_gen",
srcs: [
"protos/perfetto/trace/clock_snapshot.proto",
+ "protos/perfetto/trace/system_info.proto",
],
tools: [
"aprotoc",
@@ -1658,6 +1659,7 @@
cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
out: [
"external/perfetto/protos/perfetto/trace/clock_snapshot.pb.cc",
+ "external/perfetto/protos/perfetto/trace/system_info.pb.cc",
],
}
@@ -1666,6 +1668,7 @@
name: "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
srcs: [
"protos/perfetto/trace/clock_snapshot.proto",
+ "protos/perfetto/trace/system_info.proto",
],
tools: [
"aprotoc",
@@ -1673,6 +1676,7 @@
cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
out: [
"external/perfetto/protos/perfetto/trace/clock_snapshot.pb.h",
+ "external/perfetto/protos/perfetto/trace/system_info.pb.h",
],
export_include_dirs: [
"protos",
@@ -2146,6 +2150,7 @@
name: "perfetto_protos_perfetto_trace_zero_gen",
srcs: [
"protos/perfetto/trace/clock_snapshot.proto",
+ "protos/perfetto/trace/system_info.proto",
"protos/perfetto/trace/test_event.proto",
"protos/perfetto/trace/trace.proto",
"protos/perfetto/trace/trace_packet.proto",
@@ -2157,6 +2162,7 @@
cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
out: [
"external/perfetto/protos/perfetto/trace/clock_snapshot.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/system_info.pbzero.cc",
"external/perfetto/protos/perfetto/trace/test_event.pbzero.cc",
"external/perfetto/protos/perfetto/trace/trace.pbzero.cc",
"external/perfetto/protos/perfetto/trace/trace_packet.pbzero.cc",
@@ -2168,6 +2174,7 @@
name: "perfetto_protos_perfetto_trace_zero_gen_headers",
srcs: [
"protos/perfetto/trace/clock_snapshot.proto",
+ "protos/perfetto/trace/system_info.proto",
"protos/perfetto/trace/test_event.proto",
"protos/perfetto/trace/trace.proto",
"protos/perfetto/trace/trace_packet.proto",
@@ -2179,6 +2186,7 @@
cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
out: [
"external/perfetto/protos/perfetto/trace/clock_snapshot.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/system_info.pbzero.h",
"external/perfetto/protos/perfetto/trace/test_event.pbzero.h",
"external/perfetto/protos/perfetto/trace/trace.pbzero.h",
"external/perfetto/protos/perfetto/trace/trace_packet.pbzero.h",
@@ -2945,7 +2953,6 @@
"src/tracing/core/packet_stream_validator_unittest.cc",
"src/tracing/core/patch_list_unittest.cc",
"src/tracing/core/process_stats_config.cc",
- "src/tracing/core/service_impl_unittest.cc",
"src/tracing/core/shared_memory_abi.cc",
"src/tracing/core/shared_memory_abi_unittest.cc",
"src/tracing/core/shared_memory_arbiter_impl.cc",
@@ -2967,6 +2974,7 @@
"src/tracing/core/trace_writer_impl.cc",
"src/tracing/core/trace_writer_impl_unittest.cc",
"src/tracing/core/tracing_service_impl.cc",
+ "src/tracing/core/tracing_service_impl_unittest.cc",
"src/tracing/core/virtual_destructors.cc",
"src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
"src/tracing/ipc/default_socket.cc",
diff --git a/protos/perfetto/trace/BUILD.gn b/protos/perfetto/trace/BUILD.gn
index 81dcad2..5369d9a 100644
--- a/protos/perfetto/trace/BUILD.gn
+++ b/protos/perfetto/trace/BUILD.gn
@@ -18,7 +18,10 @@
# Common protos used by both the ":minimal_lite" target (for the service) and
# the generic ":lite" target
-proto_sources_minimal = [ "clock_snapshot.proto" ]
+proto_sources_minimal = [
+ "clock_snapshot.proto",
+ "system_info.proto",
+]
proto_sources_trusted = [ "trusted_packet.proto" ]
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 08242bc..96561d1 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -2403,6 +2403,67 @@
// End of protos/perfetto/trace/power/power_rails.proto
+// Begin of protos/perfetto/trace/profiling/profile_packet.proto
+
+message ProfilePacket {
+ // either a function or library name.
+ repeated InternedString strings = 1;
+ message InternedString {
+ optional uint64 id = 1;
+ optional bytes str = 2;
+ }
+
+ repeated Frame frames = 2;
+ message Frame {
+ optional uint64 id = 1; // Interning key
+ // E.g. "fopen"
+ optional uint64 function_name_id = 2; // id of string.
+ optional uint64 mapping_id = 3;
+ optional uint64 rel_pc = 4;
+ }
+
+ repeated Callstack callstacks = 3;
+ message Callstack {
+ optional uint64 id = 1;
+ // Frames of this callstack. Bottom frame first.
+ repeated uint64 frame_ids = 2;
+ }
+
+ repeated Mapping mappings = 4;
+ message Mapping {
+ optional uint64 id = 1; // Interning key.
+ optional uint64 build_id = 2; // Interning key.
+ optional uint64 offset = 3;
+ optional uint64 start = 4;
+ optional uint64 end = 5;
+ optional uint64 load_bias = 6;
+ // E.g. ["system", "lib64", "libc.so"]
+ repeated uint64 path_string_ids = 7; // id of string.
+ }
+
+ message HeapSample {
+ optional uint64 callstack_id = 1;
+ // bytes allocated at this frame.
+ optional uint64 self_allocated = 2;
+ // bytes freed at this frame.
+ optional uint64 self_freed = 3;
+ optional uint64 timestamp = 4; // timestamp [opt]
+ optional uint64 alloc_count = 5;
+ optional uint64 free_count = 6;
+ }
+
+ repeated ProcessHeapSamples process_dumps = 5;
+ message ProcessHeapSamples {
+ optional uint64 pid = 1;
+ repeated HeapSample samples = 2;
+ }
+
+ optional bool continued = 6;
+ optional uint64 index = 7;
+}
+
+// End of protos/perfetto/trace/profiling/profile_packet.proto
+
// Begin of protos/perfetto/trace/ps/process_stats.proto
// Per-process periodically sampled stats. These samples are wrapped in a
@@ -2532,6 +2593,21 @@
// End of protos/perfetto/trace/sys_stats/sys_stats.proto
+// Begin of protos/perfetto/trace/system_info.proto
+
+message Utsname {
+ optional string sysname = 1;
+ optional string version = 2;
+ optional string release = 3;
+ optional string machine = 4;
+}
+
+message SystemInfo {
+ optional Utsname utsname = 1;
+}
+
+// End of protos/perfetto/trace/system_info.proto
+
// Begin of protos/perfetto/trace/trace.proto
message Trace {
@@ -2552,7 +2628,7 @@
// TracePacket(s).
//
// Next reserved id: 13 (up to 15).
-// Next id: 45.
+// Next id: 46.
message TracePacket {
// TODO(primiano): in future we should add a timestamp_clock_domain field to
// allow mixing timestamps from different clock domains.
@@ -2578,6 +2654,7 @@
BatteryCounters battery = 38;
PowerRails power_rails = 40;
AndroidLogPacket android_log = 39;
+ SystemInfo system_info = 45;
// Only used by TrackEvent.
ProcessDescriptor process_descriptor = 43;
@@ -2920,67 +2997,6 @@
// End of protos/perfetto/trace/track_event/track_event.proto
-// Begin of protos/perfetto/trace/profiling/profile_packet.proto
-
-message ProfilePacket {
- // either a function or library name.
- repeated InternedString strings = 1;
- message InternedString {
- optional uint64 id = 1;
- optional bytes str = 2;
- }
-
- repeated Frame frames = 2;
- message Frame {
- optional uint64 id = 1; // Interning key
- // E.g. "fopen"
- optional uint64 function_name_id = 2; // id of string.
- optional uint64 mapping_id = 3;
- optional uint64 rel_pc = 4;
- }
-
- repeated Callstack callstacks = 3;
- message Callstack {
- optional uint64 id = 1;
- // Frames of this callstack. Bottom frame first.
- repeated uint64 frame_ids = 2;
- }
-
- repeated Mapping mappings = 4;
- message Mapping {
- optional uint64 id = 1; // Interning key.
- optional uint64 build_id = 2; // Interning key.
- optional uint64 offset = 3;
- optional uint64 start = 4;
- optional uint64 end = 5;
- optional uint64 load_bias = 6;
- // E.g. ["system", "lib64", "libc.so"]
- repeated uint64 path_string_ids = 7; // id of string.
- }
-
- message HeapSample {
- optional uint64 callstack_id = 1;
- // bytes allocated at this frame.
- optional uint64 self_allocated = 2;
- // bytes freed at this frame.
- optional uint64 self_freed = 3;
- optional uint64 timestamp = 4; // timestamp [opt]
- optional uint64 alloc_count = 5;
- optional uint64 free_count = 6;
- }
-
- repeated ProcessHeapSamples process_dumps = 5;
- message ProcessHeapSamples {
- optional uint64 pid = 1;
- repeated HeapSample samples = 2;
- }
-
- optional bool continued = 6;
- optional uint64 index = 7;
-}
-
-// End of protos/perfetto/trace/profiling/profile_packet.proto
-
// Begin of protos/perfetto/config/android/android_log_config.proto
message AndroidLogConfig {
diff --git a/protos/perfetto/trace/profiling/profile_packet.proto b/protos/perfetto/trace/profiling/profile_packet.proto
index 91818b4..9e32fcc 100644
--- a/protos/perfetto/trace/profiling/profile_packet.proto
+++ b/protos/perfetto/trace/profiling/profile_packet.proto
@@ -45,7 +45,7 @@
repeated Mapping mappings = 4;
message Mapping {
- optional uint64 id = 1; // Interning key.
+ optional uint64 id = 1; // Interning key.
optional uint64 build_id = 2; // Interning key.
optional uint64 offset = 3;
optional uint64 start = 4;
diff --git a/protos/perfetto/trace/system_info.proto b/protos/perfetto/trace/system_info.proto
new file mode 100644
index 0000000..28f4763
--- /dev/null
+++ b/protos/perfetto/trace/system_info.proto
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+message Utsname {
+ optional string sysname = 1;
+ optional string version = 2;
+ optional string release = 3;
+ optional string machine = 4;
+}
+
+message SystemInfo {
+ optional Utsname utsname = 1;
+}
diff --git a/protos/perfetto/trace/trace_packet.proto b/protos/perfetto/trace/trace_packet.proto
index 44f61ac..846e961 100644
--- a/protos/perfetto/trace/trace_packet.proto
+++ b/protos/perfetto/trace/trace_packet.proto
@@ -22,9 +22,6 @@
import "perfetto/trace/android/android_log.proto";
import "perfetto/trace/chrome/chrome_trace_event.proto";
import "perfetto/trace/clock_snapshot.proto";
-import "perfetto/trace/track_event/process_descriptor.proto";
-import "perfetto/trace/track_event/thread_descriptor.proto";
-import "perfetto/trace/track_event/track_event.proto";
import "perfetto/trace/filesystem/inode_file_map.proto";
import "perfetto/trace/ftrace/ftrace_event_bundle.proto";
import "perfetto/trace/ftrace/ftrace_stats.proto";
@@ -35,7 +32,11 @@
import "perfetto/trace/ps/process_stats.proto";
import "perfetto/trace/ps/process_tree.proto";
import "perfetto/trace/sys_stats/sys_stats.proto";
+import "perfetto/trace/system_info.proto";
import "perfetto/trace/test_event.proto";
+import "perfetto/trace/track_event/process_descriptor.proto";
+import "perfetto/trace/track_event/thread_descriptor.proto";
+import "perfetto/trace/track_event/track_event.proto";
package perfetto.protos;
@@ -43,7 +44,7 @@
// TracePacket(s).
//
// Next reserved id: 13 (up to 15).
-// Next id: 45.
+// Next id: 46.
message TracePacket {
// TODO(primiano): in future we should add a timestamp_clock_domain field to
// allow mixing timestamps from different clock domains.
@@ -69,6 +70,7 @@
BatteryCounters battery = 38;
PowerRails power_rails = 40;
AndroidLogPacket android_log = 39;
+ SystemInfo system_info = 45;
// Only used by TrackEvent.
ProcessDescriptor process_descriptor = 43;
diff --git a/protos/perfetto/trace/trusted_packet.proto b/protos/perfetto/trace/trusted_packet.proto
index f656b37..0e04c9a 100644
--- a/protos/perfetto/trace/trusted_packet.proto
+++ b/protos/perfetto/trace/trusted_packet.proto
@@ -29,6 +29,7 @@
import "perfetto/common/trace_stats.proto";
import "perfetto/config/trace_config.proto";
import "perfetto/trace/clock_snapshot.proto";
+import "perfetto/trace/system_info.proto";
package perfetto.protos;
@@ -56,4 +57,5 @@
TraceStats trace_stats = 35;
bytes synchronization_marker = 36;
uint32 previous_packet_dropped = 42;
+ SystemInfo system_info = 45;
}
diff --git a/src/trace_processor/args_table.cc b/src/trace_processor/args_table.cc
index 505a907..b628d14 100644
--- a/src/trace_processor/args_table.cc
+++ b/src/trace_processor/args_table.cc
@@ -103,24 +103,27 @@
case VariadicType::kInt: {
bool op_is_null = sqlite_utils::IsOpIsNull(op);
auto predicate = sqlite_utils::CreateNumericPredicate<int64_t>(op, value);
- index->FilterRows([this, &predicate, op_is_null](uint32_t row) {
- const auto& arg = storage_->args().arg_values()[row];
- return arg.type == type_ ? predicate(arg.int_value) : op_is_null;
- });
+ index->FilterRows(
+ [this, predicate, op_is_null](uint32_t row) PERFETTO_ALWAYS_INLINE {
+ const auto& arg = storage_->args().arg_values()[row];
+ return arg.type == type_ ? predicate(arg.int_value) : op_is_null;
+ });
break;
}
case VariadicType::kReal: {
bool op_is_null = sqlite_utils::IsOpIsNull(op);
auto predicate = sqlite_utils::CreateNumericPredicate<double>(op, value);
- index->FilterRows([this, &predicate, op_is_null](uint32_t row) {
- const auto& arg = storage_->args().arg_values()[row];
- return arg.type == type_ ? predicate(arg.real_value) : op_is_null;
- });
+ index->FilterRows(
+ [this, predicate, op_is_null](uint32_t row) PERFETTO_ALWAYS_INLINE {
+ const auto& arg = storage_->args().arg_values()[row];
+ return arg.type == type_ ? predicate(arg.real_value) : op_is_null;
+ });
break;
}
case VariadicType::kString: {
auto predicate = sqlite_utils::CreateStringPredicate(op, value);
- index->FilterRows([this, &predicate](uint32_t row) {
+ index->FilterRows([this,
+ &predicate](uint32_t row) PERFETTO_ALWAYS_INLINE {
const auto& arg = storage_->args().arg_values()[row];
return arg.type == type_
? predicate(storage_->GetString(arg.string_value).c_str())
diff --git a/src/trace_processor/counters_table.h b/src/trace_processor/counters_table.h
index d672350..84ff4d8 100644
--- a/src/trace_processor/counters_table.h
+++ b/src/trace_processor/counters_table.h
@@ -17,11 +17,12 @@
#ifndef SRC_TRACE_PROCESSOR_COUNTERS_TABLE_H_
#define SRC_TRACE_PROCESSOR_COUNTERS_TABLE_H_
-#include "src/trace_processor/storage_table.h"
-
#include <deque>
#include <memory>
#include <string>
+#include <vector>
+
+#include "src/trace_processor/storage_table.h"
namespace perfetto {
namespace trace_processor {
@@ -67,7 +68,7 @@
};
private:
- std::deque<std::string> ref_types_;
+ std::vector<std::string> ref_types_;
const TraceStorage* const storage_;
};
} // namespace trace_processor
diff --git a/src/trace_processor/filtered_row_index.h b/src/trace_processor/filtered_row_index.h
index 275d83d..d8dcaeb 100644
--- a/src/trace_processor/filtered_row_index.h
+++ b/src/trace_processor/filtered_row_index.h
@@ -54,8 +54,8 @@
// Calls |fn| on each row index which is currently to be returned and retains
// row index if |fn| returns true or discards the row otherwise.
- template <typename Predicate>
- void FilterRows(Predicate fn) {
+ template <typename RowPredicate /* (uint32_t) -> bool */>
+ void FilterRows(RowPredicate fn) {
PERFETTO_DCHECK(error_.empty());
switch (mode_) {
@@ -99,10 +99,11 @@
template <typename Predicate>
void FilterAllRows(Predicate fn) {
mode_ = Mode::kBitVector;
- row_filter_.resize(end_row_ - start_row_, true);
+ row_filter_.resize(end_row_ - start_row_, false);
- for (uint32_t i = start_row_; i < end_row_; i++) {
- row_filter_[i - start_row_] = fn(i);
+ for (auto i = start_row_; i < end_row_; i++) {
+ if (fn(i))
+ row_filter_[i - start_row_] = true;
}
}
@@ -110,10 +111,12 @@
void FilterBitVector(Predicate fn) {
auto b = row_filter_.begin();
auto e = row_filter_.end();
+
using std::find;
for (auto it = find(b, e, true); it != e; it = find(it + 1, e, true)) {
auto filter_idx = static_cast<uint32_t>(std::distance(b, it));
- *it = fn(start_row_ + filter_idx);
+ auto value_it = start_row_ + filter_idx;
+ *it = fn(value_it);
}
}
diff --git a/src/trace_processor/instants_table.h b/src/trace_processor/instants_table.h
index f19f5fc..baee499 100644
--- a/src/trace_processor/instants_table.h
+++ b/src/trace_processor/instants_table.h
@@ -17,6 +17,9 @@
#ifndef SRC_TRACE_PROCESSOR_INSTANTS_TABLE_H_
#define SRC_TRACE_PROCESSOR_INSTANTS_TABLE_H_
+#include <string>
+#include <vector>
+
#include "src/trace_processor/storage_table.h"
#include "src/trace_processor/trace_storage.h"
@@ -35,7 +38,7 @@
int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
private:
- std::deque<std::string> ref_types_;
+ std::vector<std::string> ref_types_;
const TraceStorage* const storage_;
};
} // namespace trace_processor
diff --git a/src/trace_processor/process_table.cc b/src/trace_processor/process_table.cc
index 09e42c7..7aac10e 100644
--- a/src/trace_processor/process_table.cc
+++ b/src/trace_processor/process_table.cc
@@ -108,8 +108,7 @@
case Column::kName: {
const auto& process = storage_->GetProcess(current);
const auto& name = storage_->GetString(process.name_id);
- sqlite3_result_text(context, name.c_str(),
- static_cast<int>(name.length()), kSqliteStatic);
+ sqlite3_result_text(context, name.c_str(), -1, kSqliteStatic);
break;
}
case Column::kPid: {
diff --git a/src/trace_processor/process_tracker.cc b/src/trace_processor/process_tracker.cc
index 5fc15cc..33fdfcc 100644
--- a/src/trace_processor/process_tracker.cc
+++ b/src/trace_processor/process_tracker.cc
@@ -123,13 +123,15 @@
base::StringView name) {
auto proc_name_id = context_->storage->InternString(name);
+ base::Optional<UniquePid> pupid;
+ if (ppid.has_value()) {
+ pupid = GetOrCreateProcess(ppid.value(), 0 /* start_ns */).first;
+ }
UniquePid upid;
TraceStorage::Process* process;
std::tie(upid, process) = GetOrCreateProcess(pid, 0 /* start_ns */);
process->name_id = proc_name_id;
- if (ppid.has_value()) {
- process->pupid = GetOrCreateProcess(ppid.value(), 0 /* start_ns */).first;
- }
+ process->pupid = pupid;
return upid;
}
diff --git a/src/trace_processor/sqlite_utils.h b/src/trace_processor/sqlite_utils.h
index 9974e05..7f5d732 100644
--- a/src/trace_processor/sqlite_utils.h
+++ b/src/trace_processor/sqlite_utils.h
@@ -90,6 +90,10 @@
return op == SQLITE_INDEX_CONSTRAINT_ISNULL;
}
+inline bool IsOpIsNotNull(int op) {
+ return op == SQLITE_INDEX_CONSTRAINT_ISNOTNULL;
+}
+
template <typename T>
T ExtractSqliteValue(sqlite3_value* value);
@@ -140,34 +144,46 @@
return std::string(extracted);
}
-template <typename T, typename sqlite_utils::is_numeric<T>* = nullptr>
-std::function<bool(T)> CreateNumericPredicate(int op, sqlite3_value* value) {
- switch (op) {
- case SQLITE_INDEX_CONSTRAINT_ISNULL:
- return [](T) { return false; };
- case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
- return [](T) { return true; };
+template <typename T>
+class NumericPredicate {
+ public:
+ NumericPredicate(int op, T constant) : op_(op), constant_(constant) {}
+
+ PERFETTO_ALWAYS_INLINE bool operator()(T other) const {
+ switch (op_) {
+ case SQLITE_INDEX_CONSTRAINT_ISNULL:
+ return false;
+ case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
+ return true;
+ case SQLITE_INDEX_CONSTRAINT_EQ:
+ case SQLITE_INDEX_CONSTRAINT_IS:
+ return std::equal_to<T>()(other, constant_);
+ case SQLITE_INDEX_CONSTRAINT_NE:
+ case SQLITE_INDEX_CONSTRAINT_ISNOT:
+ return std::not_equal_to<T>()(other, constant_);
+ case SQLITE_INDEX_CONSTRAINT_GE:
+ return std::greater_equal<T>()(other, constant_);
+ case SQLITE_INDEX_CONSTRAINT_GT:
+ return std::greater<T>()(other, constant_);
+ case SQLITE_INDEX_CONSTRAINT_LE:
+ return std::less_equal<T>()(other, constant_);
+ case SQLITE_INDEX_CONSTRAINT_LT:
+ return std::less<T>()(other, constant_);
+ default:
+ PERFETTO_FATAL("For GCC");
+ }
}
- T val = ExtractSqliteValue<T>(value);
- switch (op) {
- case SQLITE_INDEX_CONSTRAINT_EQ:
- case SQLITE_INDEX_CONSTRAINT_IS:
- return [val](T f) { return std::equal_to<T>()(f, val); };
- case SQLITE_INDEX_CONSTRAINT_NE:
- case SQLITE_INDEX_CONSTRAINT_ISNOT:
- return [val](T f) { return std::not_equal_to<T>()(f, val); };
- case SQLITE_INDEX_CONSTRAINT_GE:
- return [val](T f) { return f >= val; };
- case SQLITE_INDEX_CONSTRAINT_GT:
- return [val](T f) { return f > val; };
- case SQLITE_INDEX_CONSTRAINT_LE:
- return [val](T f) { return f <= val; };
- case SQLITE_INDEX_CONSTRAINT_LT:
- return [val](T f) { return f < val; };
- default:
- PERFETTO_FATAL("For GCC");
- }
+ private:
+ int op_;
+ T constant_;
+};
+
+template <typename T, typename sqlite_utils::is_numeric<T>* = nullptr>
+NumericPredicate<T> CreateNumericPredicate(int op, sqlite3_value* value) {
+ T extracted =
+ IsOpIsNull(op) || IsOpIsNotNull(op) ? 0 : ExtractSqliteValue<T>(value);
+ return NumericPredicate<T>(op, extracted);
}
inline std::function<bool(const char*)> CreateStringPredicate(
diff --git a/src/trace_processor/storage_columns.cc b/src/trace_processor/storage_columns.cc
index 8dfc381..25cda66 100644
--- a/src/trace_processor/storage_columns.cc
+++ b/src/trace_processor/storage_columns.cc
@@ -46,7 +46,7 @@
sqlite3_value* value,
FilteredRowIndex* index) const {
auto predicate = sqlite_utils::CreateNumericPredicate<int64_t>(op, value);
- index->FilterRows([this, &predicate](uint32_t row) {
+ index->FilterRows([this, predicate](uint32_t row) PERFETTO_ALWAYS_INLINE {
return predicate((*ts_start_)[row] + (*dur_)[row]);
});
}
diff --git a/src/trace_processor/storage_columns.h b/src/trace_processor/storage_columns.h
index 0a3f158..7945bd7 100644
--- a/src/trace_processor/storage_columns.h
+++ b/src/trace_processor/storage_columns.h
@@ -16,8 +16,10 @@
#define SRC_TRACE_PROCESSOR_STORAGE_COLUMNS_H_
#include <deque>
+#include <limits>
#include <memory>
#include <string>
+#include <vector>
#include "src/trace_processor/filtered_row_index.h"
#include "src/trace_processor/sqlite_utils.h"
@@ -199,9 +201,11 @@
sqlite3_value* value,
FilteredRowIndex* index) const {
auto predicate = sqlite_utils::CreateNumericPredicate<C>(op, value);
- index->FilterRows([this, &predicate](uint32_t row) {
+ auto cast_predicate = [this,
+ predicate](uint32_t row) PERFETTO_ALWAYS_INLINE {
return predicate(static_cast<C>((*deque_)[row]));
- });
+ };
+ index->FilterRows(cast_predicate);
}
bool is_naturally_ordered_ = false;
@@ -212,7 +216,7 @@
public:
StringColumn(std::string col_name,
const std::deque<Id>* deque,
- const std::deque<std::string>* string_map,
+ const std::vector<std::string>* string_map,
bool hidden = false)
: StorageColumn(col_name, hidden),
deque_(deque),
@@ -258,7 +262,7 @@
private:
const std::deque<Id>* deque_ = nullptr;
- const std::deque<std::string>* string_map_ = nullptr;
+ const std::vector<std::string>* string_map_ = nullptr;
};
// Column which represents the "ts_end" column present in all time based
@@ -268,7 +272,7 @@
TsEndColumn(std::string col_name,
const std::deque<int64_t>* ts_start,
const std::deque<int64_t>* dur);
- virtual ~TsEndColumn() override;
+ ~TsEndColumn() override;
void ReportResult(sqlite3_context*, uint32_t) const override;
@@ -295,7 +299,7 @@
class IdColumn final : public StorageColumn {
public:
IdColumn(std::string column_name, TableId table_id);
- virtual ~IdColumn() override;
+ ~IdColumn() override;
void ReportResult(sqlite3_context* ctx, uint32_t row) const override {
auto id = TraceStorage::CreateRowId(table_id_, row);
@@ -308,7 +312,7 @@
sqlite3_value* value,
FilteredRowIndex* index) const override {
auto predicate = sqlite_utils::CreateNumericPredicate<RowId>(op, value);
- index->FilterRows([this, &predicate](uint32_t row) {
+ index->FilterRows([this, predicate](uint32_t row) PERFETTO_ALWAYS_INLINE {
return predicate(TraceStorage::CreateRowId(table_id_, row));
});
}
diff --git a/src/trace_processor/storage_schema.h b/src/trace_processor/storage_schema.h
index ae77643..ee7452d 100644
--- a/src/trace_processor/storage_schema.h
+++ b/src/trace_processor/storage_schema.h
@@ -16,6 +16,11 @@
#define SRC_TRACE_PROCESSOR_STORAGE_SCHEMA_H_
#include <algorithm>
+#include <deque>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
#include "src/trace_processor/filtered_row_index.h"
#include "src/trace_processor/sqlite_utils.h"
@@ -63,7 +68,7 @@
template <class Id>
Builder& AddStringColumn(std::string column_name,
const std::deque<Id>* ids,
- const std::deque<std::string>* string_map) {
+ const std::vector<std::string>* string_map) {
columns_.emplace_back(new StringColumn<Id>(column_name, ids, string_map));
return *this;
}
diff --git a/src/trace_processor/thread_table.cc b/src/trace_processor/thread_table.cc
index 0a38faa..a641243 100644
--- a/src/trace_processor/thread_table.cc
+++ b/src/trace_processor/thread_table.cc
@@ -118,8 +118,7 @@
}
case Column::kName: {
const auto& name = storage_->GetString(thread.name_id);
- sqlite3_result_text(context, name.c_str(),
- static_cast<int>(name.length()), kSqliteStatic);
+ sqlite3_result_text(context, name.c_str(), -1, kSqliteStatic);
break;
}
case Column::kTid: {
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 22a3427..ca942db 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -610,7 +610,7 @@
const RawEvents& raw_events() const { return raw_events_; }
RawEvents* mutable_raw_events() { return &raw_events_; }
- const std::deque<std::string>& string_pool() const { return string_pool_; }
+ const std::vector<std::string>& string_pool() const { return string_pool_; }
// |unique_processes_| always contains at least 1 element becuase the 0th ID
// is reserved to indicate an invalid process.
@@ -644,13 +644,15 @@
Args args_;
// One entry for each unique string in the trace.
- std::deque<std::string> string_pool_;
+ std::vector<std::string> string_pool_;
// One entry for each unique string in the trace.
std::unordered_map<StringHash, StringId> string_index_;
// One entry for each UniquePid, with UniquePid as the index.
- std::deque<Process> unique_processes_;
+ // Never hold on to pointers to Process, as vector resize will
+ // invalidate them.
+ std::vector<Process> unique_processes_;
// One entry for each UniqueTid, with UniqueTid as the index.
std::deque<Thread> unique_threads_;
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index 06969cc..b018f84 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -113,10 +113,10 @@
# has no Windows implementation.
if (!is_win) {
sources += [
- "core/service_impl_unittest.cc",
"core/shared_memory_arbiter_impl_unittest.cc",
"core/startup_trace_writer_unittest.cc",
"core/trace_writer_impl_unittest.cc",
+ "core/tracing_service_impl_unittest.cc",
"test/fake_producer_endpoint.h",
"test/mock_consumer.cc",
"test/mock_consumer.h",
diff --git a/src/tracing/core/trace_buffer.cc b/src/tracing/core/trace_buffer.cc
index 266a08b..4af9b6d 100644
--- a/src/tracing/core/trace_buffer.cc
+++ b/src/tracing/core/trace_buffer.cc
@@ -663,17 +663,25 @@
if (action == kReadOnePacket) {
// The easy peasy case B.
- if (PERFETTO_LIKELY(ReadNextPacketInChunk(chunk_meta, packet))) {
+ ReadPacketResult result = ReadNextPacketInChunk(chunk_meta, packet);
+
+ if (PERFETTO_LIKELY(result == ReadPacketResult::kSucceeded)) {
*sequence_properties = {trusted_producer_id, trusted_uid, writer_id};
*previous_packet_on_sequence_dropped = previous_packet_dropped;
return true;
+ } else if (result == ReadPacketResult::kFailedEmptyPacket) {
+ // We can ignore and skip empty packets.
+ PERFETTO_DCHECK(packet->slices().empty());
+ continue;
}
// In extremely rare cases (producer bugged / malicious) the chunk might
// contain an invalid fragment. In such case we don't want to stall the
- // sequence but just skip the chunk and move on.
- stats_.set_abi_violations(stats_.abi_violations() + 1);
- PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
+ // sequence but just skip the chunk and move on. ReadNextPacketInChunk()
+ // marks the chunk as fully read, so we don't attempt to read from it
+ // again in a future call to ReadBuffers(). It also already records an
+ // abi violation for this.
+ PERFETTO_DCHECK(result == ReadPacketResult::kFailedInvalidPacket);
chunk_meta->set_last_read_packet_skipped(true);
previous_packet_dropped = true;
break;
@@ -771,10 +779,11 @@
PERFETTO_DCHECK(read_iter_.is_valid());
TRACE_BUFFER_DLOG(" commit chunk %u", read_iter_.chunk_id());
if (PERFETTO_LIKELY((*read_iter_).num_fragments > 0)) {
- // In the unlikely case of a corrupted packet, invalidate the all
- // stitching and move on to the next chunk in the same sequence,
- // if any.
- packet_corruption |= !ReadNextPacketInChunk(&*read_iter_, packet);
+ // In the unlikely case of a corrupted packet (corrupted or empty
+ // fragment), invalidate the all stitching and move on to the next chunk
+ // in the same sequence, if any.
+ packet_corruption |= ReadNextPacketInChunk(&*read_iter_, packet) ==
+ ReadPacketResult::kFailedInvalidPacket;
}
if (read_iter_.cur == it.cur)
break;
@@ -783,8 +792,7 @@
PERFETTO_DCHECK(read_iter_.cur == it.cur);
if (PERFETTO_UNLIKELY(packet_corruption)) {
- stats_.set_abi_violations(stats_.abi_violations() + 1);
- PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
+ // ReadNextPacketInChunk() already records an abi violation for this case.
*packet = TracePacket(); // clear.
return ReadAheadResult::kFailedStayOnSameSequence;
}
@@ -794,8 +802,9 @@
return ReadAheadResult::kFailedMoveToNextSequence;
}
-bool TraceBuffer::ReadNextPacketInChunk(ChunkMeta* chunk_meta,
- TracePacket* packet) {
+TraceBuffer::ReadPacketResult TraceBuffer::ReadNextPacketInChunk(
+ ChunkMeta* chunk_meta,
+ TracePacket* packet) {
PERFETTO_DCHECK(chunk_meta->num_fragments_read < chunk_meta->num_fragments);
PERFETTO_DCHECK(!(chunk_meta->flags & kChunkNeedsPatching));
@@ -811,7 +820,14 @@
// contains more packets beyond its boundaries.
stats_.set_abi_violations(stats_.abi_violations() + 1);
PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
- return false;
+ chunk_meta->cur_fragment_offset = 0;
+ chunk_meta->num_fragments_read = chunk_meta->num_fragments;
+ if (PERFETTO_LIKELY(chunk_meta->is_complete())) {
+ stats_.set_chunks_read(stats_.chunks_read() + 1);
+ stats_.set_bytes_read(stats_.bytes_read() +
+ chunk_meta->chunk_record->size);
+ }
+ return ReadPacketResult::kFailedInvalidPacket;
}
// A packet (or a fragment) starts with a varint stating its size, followed
@@ -836,8 +852,9 @@
stats_.set_bytes_read(stats_.bytes_read() +
chunk_meta->chunk_record->size);
}
- return false;
+ return ReadPacketResult::kFailedInvalidPacket;
}
+
chunk_meta->cur_fragment_offset =
static_cast<uint16_t>(next_packet - packets_begin);
chunk_meta->num_fragments_read++;
@@ -849,17 +866,15 @@
stats_.set_bytes_read(stats_.bytes_read() + chunk_meta->chunk_record->size);
}
- if (PERFETTO_UNLIKELY(packet_size == 0)) {
- stats_.set_abi_violations(stats_.abi_violations() + 1);
- PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
- return false;
- }
+ chunk_meta->set_last_read_packet_skipped(false);
+
+ if (PERFETTO_UNLIKELY(packet_size == 0))
+ return ReadPacketResult::kFailedEmptyPacket;
if (PERFETTO_LIKELY(packet))
packet->AddSlice(packet_data, static_cast<size_t>(packet_size));
- chunk_meta->set_last_read_packet_skipped(false);
- return true;
+ return ReadPacketResult::kSucceeded;
}
void TraceBuffer::DiscardWrite() {
diff --git a/src/tracing/core/trace_buffer.h b/src/tracing/core/trace_buffer.h
index cd32fdc..d86037a 100644
--- a/src/tracing/core/trace_buffer.h
+++ b/src/tracing/core/trace_buffer.h
@@ -481,6 +481,12 @@
kFailedStayOnSameSequence,
};
+ enum class ReadPacketResult {
+ kSucceeded,
+ kFailedInvalidPacket,
+ kFailedEmptyPacket,
+ };
+
explicit TraceBuffer(OverwritePolicy);
TraceBuffer(const TraceBuffer&) = delete;
TraceBuffer& operator=(const TraceBuffer&) = delete;
@@ -537,7 +543,7 @@
// TracePacket can be nullptr, in which case the read state is still advanced.
// When TracePacket is not nullptr, ProducerID must also be not null and will
// be updated with the ProducerID that originally wrote the chunk.
- bool ReadNextPacketInChunk(ChunkMeta*, TracePacket*);
+ ReadPacketResult ReadNextPacketInChunk(ChunkMeta*, TracePacket*);
void DcheckIsAlignedAndWithinBounds(const uint8_t* ptr) const {
PERFETTO_DCHECK(ptr >= begin() && ptr <= end() - sizeof(ChunkRecord));
diff --git a/src/tracing/core/trace_buffer_unittest.cc b/src/tracing/core/trace_buffer_unittest.cc
index 07a17b4..b1f60ca 100644
--- a/src/tracing/core/trace_buffer_unittest.cc
+++ b/src/tracing/core/trace_buffer_unittest.cc
@@ -461,6 +461,23 @@
ASSERT_THAT(ReadPacket(), IsEmpty());
}
+// Verify that empty packets are skipped.
+TEST_F(TraceBufferTest, ReadWrite_EmptyPacket) {
+ ResetBuffer(4096);
+ CreateChunk(ProducerID(1), WriterID(1), 0)
+ .AddPacket(42, 1)
+ .AddPacket(1, 2)
+ .AddPacket(42, 3)
+ .CopyIntoTraceBuffer();
+
+ trace_buffer()->BeginRead();
+ ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(42, 1)));
+ ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(42, 3)));
+ ASSERT_THAT(ReadPacket(), IsEmpty());
+
+ EXPECT_EQ(0u, trace_buffer()->stats().abi_violations());
+}
+
// --------------------------------------
// Fragments stitching and skipping logic
// --------------------------------------
@@ -1071,7 +1088,8 @@
}
// Like the Malicious_ZeroVarintHeader, but put the chunk in the middle of a
-// sequence that would be otherwise valid.
+// sequence that would be otherwise valid. The zero-sized fragment should be
+// skipped.
TEST_F(TraceBufferTest, Malicious_ZeroVarintHeaderInSequence) {
ResetBuffer(4096);
SuppressSanityDchecksForTesting();
@@ -1094,17 +1112,17 @@
.CopyIntoTraceBuffer();
trace_buffer()->BeginRead();
+ ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(4, 'a'),
+ FakePacketFragment(4, 'c')));
ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(4, 'd')));
ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(4, 'e')));
ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(5, 'f')));
ASSERT_THAT(ReadPacket(), IsEmpty());
}
-// Similar to Malicious_ZeroVarintHeader, but this time the zero-sized fragment
-// is the last fragment for a chunk and is marked for continuation.
-// One might argue that this case is borderline legit, and in this case we
-// should just read a packet consisting of (4, 'c'). However this is too complex
-// to support and doesn't bring any benefit.
+// Similar to Malicious_ZeroVarintHeaderInSequence, but this time the zero-sized
+// fragment is the last fragment for a chunk and is marked for continuation. The
+// zero-sized fragment should be skipped.
TEST_F(TraceBufferTest, Malicious_ZeroVarintHeaderAtEndOfChunk) {
ResetBuffer(4096);
SuppressSanityDchecksForTesting();
@@ -1126,6 +1144,7 @@
trace_buffer()->BeginRead();
ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(4, 'a')));
+ ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(4, 'c')));
ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(4, 'd')));
ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(4, 'e')));
ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(4, 'f')));
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 9c00ec9..4091ead 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -25,6 +25,7 @@
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <sys/uio.h>
+#include <sys/utsname.h>
#include <unistd.h>
#endif
@@ -50,6 +51,7 @@
#include "src/tracing/core/trace_buffer.h"
#include "perfetto/trace/clock_snapshot.pb.h"
+#include "perfetto/trace/system_info.pb.h"
#include "perfetto/trace/trusted_packet.pb.h"
// General note: this class must assume that Producers are malicious and will
@@ -1093,6 +1095,7 @@
SnapshotClocks(&packets);
}
MaybeEmitTraceConfig(tracing_session, &packets);
+ MaybeEmitSystemInfo(tracing_session, &packets);
size_t packets_bytes = 0; // SUM(slice.size() for each slice in |packets|).
size_t total_slices = 0; // SUM(#slices in |packets|).
@@ -1813,6 +1816,32 @@
packets->back().AddSlice(std::move(slice));
}
+void TracingServiceImpl::MaybeEmitSystemInfo(
+ TracingSession* tracing_session,
+ std::vector<TracePacket>* packets) {
+ if (tracing_session->did_emit_system_info)
+ return;
+ tracing_session->did_emit_system_info = true;
+ protos::TrustedPacket packet;
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ protos::SystemInfo* info = packet.mutable_system_info();
+ struct utsname uname_info;
+ if (uname(&uname_info) == 0) {
+ protos::Utsname* utsname_info = info->mutable_utsname();
+ utsname_info->set_sysname(uname_info.sysname);
+ utsname_info->set_version(uname_info.version);
+ utsname_info->set_machine(uname_info.machine);
+ utsname_info->set_release(uname_info.release);
+ }
+#endif
+ packet.set_trusted_uid(static_cast<int32_t>(uid_));
+ packet.set_trusted_packet_sequence_id(kServicePacketSequenceID);
+ Slice slice = Slice::Allocate(static_cast<size_t>(packet.ByteSize()));
+ PERFETTO_CHECK(packet.SerializeWithCachedSizesToArray(slice.own_data()));
+ packets->emplace_back();
+ packets->back().AddSlice(std::move(slice));
+}
+
////////////////////////////////////////////////////////////////////////////////
// TracingServiceImpl::ConsumerEndpointImpl implementation
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/tracing/core/tracing_service_impl.h b/src/tracing/core/tracing_service_impl.h
index d3e33ca..3731336 100644
--- a/src/tracing/core/tracing_service_impl.h
+++ b/src/tracing/core/tracing_service_impl.h
@@ -366,6 +366,9 @@
// Whether we mirrored the trace config back to the trace output yet.
bool did_emit_config = false;
+ // Whether we put the system info into the trace output yet.
+ bool did_emit_system_info = false;
+
State state = DISABLED;
// If the consumer detached the session, this variable defines the key used
@@ -410,6 +413,7 @@
void SnapshotStats(TracingSession*, std::vector<TracePacket>*);
TraceStats GetTraceStats(TracingSession* tracing_session);
void MaybeEmitTraceConfig(TracingSession*, std::vector<TracePacket>*);
+ void MaybeEmitSystemInfo(TracingSession*, std::vector<TracePacket>*);
void OnFlushTimeout(TracingSessionID, FlushRequestID);
void OnDisableTracingTimeout(TracingSessionID);
void DisableTracingNotifyConsumerAndFlushFile(TracingSession*);
diff --git a/src/tracing/core/service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc
similarity index 99%
rename from src/tracing/core/service_impl_unittest.cc
rename to src/tracing/core/tracing_service_impl_unittest.cc
index 81f4634..eca7d6d 100644
--- a/src/tracing/core/service_impl_unittest.cc
+++ b/src/tracing/core/tracing_service_impl_unittest.cc
@@ -430,7 +430,11 @@
producer->WaitForDataSourceSetup("data_source");
producer->WaitForDataSourceStart("data_source");
- static const int kNumPreamblePackets = 4;
+ // The preamble packets are:
+ // Config
+ // SystemInfo
+ // 3x unknown
+ static const int kNumPreamblePackets = 5;
static const int kNumTestPackets = 10;
static const char kPayload[] = "1234567890abcdef-";
diff --git a/src/tracing/test/fake_packet.cc b/src/tracing/test/fake_packet.cc
index 3486ca9..210f5fa 100644
--- a/src/tracing/test/fake_packet.cc
+++ b/src/tracing/test/fake_packet.cc
@@ -29,9 +29,9 @@
namespace perfetto {
FakePacketFragment::FakePacketFragment(size_t size, char prefix) {
- // |size| has to be at least == 2, because one byte will be taken just by the
+ // |size| has to be at least == 1, because one byte will be taken just by the
// varint header.
- PERFETTO_CHECK(size > 1);
+ PERFETTO_CHECK(size >= 1);
// Finding the |payload_size| from |size| is quite tricky:
// A packet with 127 bytes of payload requires:
diff --git a/src/tracing/test/tracing_integration_test.cc b/src/tracing/test/tracing_integration_test.cc
index fdac291..d536ee3 100644
--- a/src/tracing/test/tracing_integration_test.cc
+++ b/src/tracing/test/tracing_integration_test.cc
@@ -380,6 +380,8 @@
protos::Trace tmp_trace;
ASSERT_TRUE(tmp_trace.ParseFromArray(tmp_buf, static_cast<int>(rsize)));
size_t num_test_packet = 0;
+ size_t num_clock_snapshot_packet = 0;
+ size_t num_system_info_packet = 0;
bool saw_trace_stats = false;
for (int i = 0; i < tmp_trace.packet_size(); i++) {
const protos::TracePacket& packet = tmp_trace.packet(i);
@@ -389,9 +391,15 @@
} else if (packet.has_trace_stats()) {
saw_trace_stats = true;
CheckTraceStats(packet);
+ } else if (packet.has_clock_snapshot()) {
+ num_clock_snapshot_packet++;
+ } else if (packet.has_system_info()) {
+ num_system_info_packet++;
}
}
ASSERT_TRUE(saw_trace_stats);
+ ASSERT_GT(num_clock_snapshot_packet, 0u);
+ ASSERT_GT(num_system_info_packet, 0u);
}
// TODO(primiano): add tests to cover:
diff --git a/test/end_to_end_integrationtest.cc b/test/end_to_end_integrationtest.cc
index 5b43527..e1017d5 100644
--- a/test/end_to_end_integrationtest.cc
+++ b/test/end_to_end_integrationtest.cc
@@ -361,7 +361,7 @@
ds_config->set_name("android.perfetto.FakeProducer");
ds_config->set_target_buffer(0);
- static constexpr size_t kNumPackets = 10;
+ static constexpr size_t kNumPackets = 11;
static constexpr uint32_t kRandomSeed = 42;
static constexpr uint32_t kMsgSize = 1024;
ds_config->mutable_for_testing()->set_seed(kRandomSeed);
@@ -402,7 +402,7 @@
ds_config->set_name("android.perfetto.FakeProducer");
ds_config->set_target_buffer(0);
- static constexpr size_t kNumPackets = 5;
+ static constexpr size_t kNumPackets = 7;
static constexpr uint32_t kRandomSeed = 42;
static constexpr uint32_t kMsgSize = 1024 * 1024 - 42;
ds_config->mutable_for_testing()->set_seed(kRandomSeed);
@@ -438,7 +438,7 @@
trace_config.set_duration_ms(10000); // Max timeout, session is ended before.
auto* ds_config = trace_config.add_data_sources()->mutable_config();
ds_config->set_name("android.perfetto.FakeProducer");
- static constexpr size_t kNumPackets = 10;
+ static constexpr size_t kNumPackets = 11;
ds_config->mutable_for_testing()->set_message_count(kNumPackets);
ds_config->mutable_for_testing()->set_message_size(32);
diff --git a/test/test_helper.cc b/test/test_helper.cc
index e019a5f..2111c77 100644
--- a/test/test_helper.cc
+++ b/test/test_helper.cc
@@ -64,7 +64,8 @@
protos::TracePacket packet;
ASSERT_TRUE(encoded_packet.Decode(&packet));
if (packet.has_clock_snapshot() || packet.has_trace_config() ||
- packet.has_trace_stats() || !packet.synchronization_marker().empty()) {
+ packet.has_trace_stats() || !packet.synchronization_marker().empty() ||
+ packet.has_system_info()) {
continue;
}
ASSERT_EQ(protos::TracePacket::kTrustedUid,
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index 8c4ec83..ee12f10 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -68,9 +68,11 @@
'protos/perfetto/trace/interned_data/interned_data.proto',
'protos/perfetto/trace/power/battery_counters.proto',
'protos/perfetto/trace/power/power_rails.proto',
+ 'protos/perfetto/trace/profiling/profile_packet.proto',
'protos/perfetto/trace/ps/process_stats.proto',
'protos/perfetto/trace/ps/process_tree.proto',
'protos/perfetto/trace/sys_stats/sys_stats.proto',
+ 'protos/perfetto/trace/system_info.proto',
'protos/perfetto/trace/trace.proto',
'protos/perfetto/trace/trace_packet.proto',
'protos/perfetto/trace/track_event/debug_annotation.proto',
@@ -78,7 +80,6 @@
'protos/perfetto/trace/track_event/task_execution.proto',
'protos/perfetto/trace/track_event/thread_descriptor.proto',
'protos/perfetto/trace/track_event/track_event.proto',
- 'protos/perfetto/trace/profiling/profile_packet.proto',
)
MERGED_TRACE_PROTO = 'protos/perfetto/trace/perfetto_trace.proto'