Merge "trace_to_text: report overwrite events for ftrace"
diff --git a/gn/standalone/proto_library.gni b/gn/standalone/proto_library.gni
index 1401cc9..3005f78 100644
--- a/gn/standalone/proto_library.gni
+++ b/gn/standalone/proto_library.gni
@@ -38,6 +38,11 @@
generate_cc = invoker.generate_cc
}
+ generate_descriptor = ""
+ if (defined(invoker.generate_descriptor)) {
+ generate_descriptor = invoker.generate_descriptor
+ }
+
if (defined(invoker.generator_plugin_label)) {
plugin_host_label = invoker.generator_plugin_label + "($host_toolchain)"
plugin_path = get_label_info(plugin_host_label, "root_out_dir") + "/" +
@@ -67,6 +72,10 @@
protos = rebase_path(proto_sources, proto_in_dir)
protogens = []
+ if (generate_descriptor != "") {
+ protogens += [ "$root_gen_dir/" + generate_descriptor ]
+ }
+
foreach(proto, protos) {
proto_dir = get_path_info(proto, "dir")
proto_name = get_path_info(proto, "name")
@@ -115,6 +124,12 @@
rel_cc_out_dir,
]
}
+ if (generate_descriptor != "") {
+ args += [
+ "--descriptor_set_out",
+ rebase_path("$root_gen_dir/" + generate_descriptor, root_build_dir),
+ ]
+ }
if (generate_with_plugin) {
plugin_path_rebased = rebase_path(plugin_path, root_build_dir)
diff --git a/protos/perfetto/trace/BUILD.gn b/protos/perfetto/trace/BUILD.gn
index d58e354..90af5e0 100644
--- a/protos/perfetto/trace/BUILD.gn
+++ b/protos/perfetto/trace/BUILD.gn
@@ -55,6 +55,7 @@
"ftrace:lite",
"ps:lite",
]
+ generate_descriptor = "$perfetto_root_path/protos/trace/trace.descriptor"
sources = proto_sources
proto_in_dir = "$perfetto_root_path/protos"
proto_out_dir = "$perfetto_root_path/protos"
diff --git a/src/ftrace_reader/BUILD.gn b/src/ftrace_reader/BUILD.gn
index 80823b4..f2e010e 100644
--- a/src/ftrace_reader/BUILD.gn
+++ b/src/ftrace_reader/BUILD.gn
@@ -147,7 +147,7 @@
}
}
-if (use_libfuzzer) {
+if (use_libfuzzer && !build_with_chromium) {
executable("cpu_reader_fuzzer") {
testonly = true
sources = [
diff --git a/src/ipc/BUILD.gn b/src/ipc/BUILD.gn
index 69c320c..701565c 100644
--- a/src/ipc/BUILD.gn
+++ b/src/ipc/BUILD.gn
@@ -46,7 +46,7 @@
]
}
-if (use_libfuzzer) {
+if (use_libfuzzer && !build_with_chromium) {
executable("buffered_frame_deserializer_fuzzer") {
sources = [
"buffered_frame_deserializer_fuzzer.cc",
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 72e9c4a..a69e47b 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -45,7 +45,7 @@
}
}
-if (use_libfuzzer) {
+if (use_libfuzzer && !build_with_chromium) {
executable("end_to_end_shared_memory_fuzzer") {
sources = [
"end_to_end_shared_memory_fuzzer.cc",
diff --git a/test/cts/end_to_end_integrationtest_cts.cc b/test/cts/end_to_end_integrationtest_cts.cc
index 4392271..d40d92f 100644
--- a/test/cts/end_to_end_integrationtest_cts.cc
+++ b/test/cts/end_to_end_integrationtest_cts.cc
@@ -15,6 +15,7 @@
*/
#include <random>
+#include <sys/system_properties.h>
#include "gtest/gtest.h"
#include "perfetto/trace/test_event.pbzero.h"
@@ -32,6 +33,16 @@
class PerfettoCtsTest : public ::testing::Test {
protected:
void TestMockProducer(const std::string& producer_name) {
+ // Filter out watches; they do not have the required infrastructure to run
+ // these tests.
+ char chars[PROP_VALUE_MAX + 1];
+ int ret = __system_property_get("ro.build.characteristics", chars);
+ ASSERT_GE(ret, 0);
+ std::string characteristics(chars);
+ if (characteristics.find("watch") != std::string::npos) {
+ return;
+ }
+
base::TestTaskRunner task_runner;
TestHelper helper(&task_runner);
diff --git a/test/end_to_end_benchmark.cc b/test/end_to_end_benchmark.cc
index 100674e..f6f3d3d 100644
--- a/test/end_to_end_benchmark.cc
+++ b/test/end_to_end_benchmark.cc
@@ -36,7 +36,7 @@
return getenv("BENCHMARK_FUNCTIONAL_TEST_ONLY") != nullptr;
}
-void BenchmarkCommon(benchmark::State& state) {
+void BenchmarkProducer(benchmark::State& state) {
base::TestTaskRunner task_runner;
TestHelper helper(&task_runner);
@@ -87,10 +87,10 @@
uint64_t wall_ns =
static_cast<uint64_t>(base::GetWallTimeNs().count()) - wall_start_ns;
- state.counters["Pro CPU"] = benchmark::Counter(100.0 * producer_ns / wall_ns);
state.counters["Ser CPU"] = benchmark::Counter(100.0 * service_ns / wall_ns);
state.counters["Ser ns/m"] =
benchmark::Counter(1.0 * service_ns / message_count);
+ state.counters["Pro CPU"] = benchmark::Counter(100.0 * producer_ns / wall_ns);
state.SetBytesProcessed(iterations * message_bytes * message_count);
// Read back the buffer just to check correctness.
@@ -110,7 +110,104 @@
}
}
-void SaturateCpuArgs(benchmark::internal::Benchmark* b) {
+static void BenchmarkConsumer(benchmark::State& state) {
+ base::TestTaskRunner task_runner;
+
+ TestHelper helper(&task_runner);
+ helper.StartServiceIfRequired();
+
+ FakeProducer* producer = helper.ConnectFakeProducer();
+ helper.ConnectConsumer();
+ helper.WaitForConsumerConnect();
+
+ TraceConfig trace_config;
+
+ static const uint32_t kBufferSizeBytes =
+ IsBenchmarkFunctionalOnly() ? 16 * 1024 : 2 * 1024 * 1024;
+ trace_config.add_buffers()->set_size_kb(kBufferSizeBytes / 1024);
+
+ static constexpr uint32_t kRandomSeed = 42;
+ uint32_t message_bytes = static_cast<uint32_t>(state.range(0));
+ uint32_t mb_per_s = static_cast<uint32_t>(state.range(1));
+ bool is_saturated_producer = mb_per_s == 0;
+
+ uint32_t message_count = kBufferSizeBytes / message_bytes;
+ uint32_t messages_per_s = mb_per_s * 1024 * 1024 / message_bytes;
+ uint32_t number_of_batches =
+ is_saturated_producer ? 0 : std::max(1u, message_count / messages_per_s);
+
+ auto* ds_config = trace_config.add_data_sources()->mutable_config();
+ ds_config->set_name("android.perfetto.FakeProducer");
+ ds_config->set_target_buffer(0);
+ ds_config->mutable_for_testing()->set_seed(kRandomSeed);
+ ds_config->mutable_for_testing()->set_message_count(message_count);
+ ds_config->mutable_for_testing()->set_message_size(message_bytes);
+ ds_config->mutable_for_testing()->set_max_messages_per_second(messages_per_s);
+
+ helper.StartTracing(trace_config);
+ helper.WaitForProducerEnabled();
+
+ uint64_t wall_start_ns = static_cast<uint64_t>(base::GetWallTimeNs().count());
+ uint64_t service_start_ns =
+ static_cast<uint64_t>(helper.service_thread()->GetThreadCPUTimeNs());
+ uint64_t consumer_start_ns =
+ static_cast<uint64_t>(base::GetThreadCPUTimeNs().count());
+ uint64_t read_time_taken_ns = 0;
+
+ uint64_t iterations = 0;
+ uint32_t counter = 0;
+ for (auto _ : state) {
+ auto cname = "produced.and.committed." + std::to_string(iterations++);
+ auto on_produced_and_committed = task_runner.CreateCheckpoint(cname);
+ producer->ProduceEventBatch(helper.WrapTask(on_produced_and_committed));
+
+ if (is_saturated_producer) {
+ // If the producer is running in saturated mode, wait until it flushes
+ // data.
+ task_runner.RunUntilCheckpoint(cname);
+
+ // Then time how long it takes to read back the data.
+ int64_t start = base::GetWallTimeNs().count();
+ helper.ReadData(counter);
+ helper.WaitForReadData(counter++);
+ read_time_taken_ns +=
+ static_cast<uint64_t>(base::GetWallTimeNs().count() - start);
+ } else {
+ // If the producer is not running in saturated mode, every second the
+ // producer will send a batch of data over. Wait for a second before
+ // performing readback; do this for each batch the producer sends.
+ for (uint32_t i = 0; i < number_of_batches; i++) {
+ auto batch_cname = "batch.checkpoint." + std::to_string(counter);
+ auto batch_checkpoint = task_runner.CreateCheckpoint(batch_cname);
+ task_runner.PostDelayedTask(batch_checkpoint, 1000);
+ task_runner.RunUntilCheckpoint(batch_cname);
+
+ int64_t start = base::GetWallTimeNs().count();
+ helper.ReadData(counter);
+ helper.WaitForReadData(counter++);
+ read_time_taken_ns +=
+ static_cast<uint64_t>(base::GetWallTimeNs().count() - start);
+ }
+ }
+ }
+ uint64_t service_ns =
+ helper.service_thread()->GetThreadCPUTimeNs() - service_start_ns;
+ uint64_t consumer_ns =
+ static_cast<uint64_t>(base::GetThreadCPUTimeNs().count()) -
+ consumer_start_ns;
+ uint64_t wall_ns =
+ static_cast<uint64_t>(base::GetWallTimeNs().count()) - wall_start_ns;
+
+ state.counters["Ser CPU"] = benchmark::Counter(100.0 * service_ns / wall_ns);
+ state.counters["Ser ns/m"] =
+ benchmark::Counter(1.0 * service_ns / message_count);
+ state.counters["Con CPU"] = benchmark::Counter(100.0 * consumer_ns / wall_ns);
+ state.counters["Con Speed"] =
+ benchmark::Counter(iterations * 1000.0 * 1000 * 1000 * kBufferSizeBytes /
+ read_time_taken_ns);
+}
+
+void SaturateCpuProducerArgs(benchmark::internal::Benchmark* b) {
int min_message_count = 16;
int max_message_count = IsBenchmarkFunctionalOnly() ? 1024 : 1024 * 1024;
int min_payload = 8;
@@ -122,7 +219,7 @@
}
}
-void ConstantRateArgs(benchmark::internal::Benchmark* b) {
+void ConstantRateProducerArgs(benchmark::internal::Benchmark* b) {
int message_count = IsBenchmarkFunctionalOnly() ? 2 * 1024 : 128 * 1024;
int min_speed = IsBenchmarkFunctionalOnly() ? 64 : 8;
int max_speed = IsBenchmarkFunctionalOnly() ? 128 : 128;
@@ -131,23 +228,60 @@
b->Args({message_count, 256, speed});
}
}
+
+void SaturateCpuConsumerArgs(benchmark::internal::Benchmark* b) {
+ int min_payload = 8;
+ int max_payload = IsBenchmarkFunctionalOnly() ? 16 : 64 * 1024;
+ for (int bytes = min_payload; bytes <= max_payload; bytes *= 2) {
+ b->Args({bytes, 0 /* speed */});
+ }
+}
+
+void ConstantRateConsumerArgs(benchmark::internal::Benchmark* b) {
+ int min_speed = IsBenchmarkFunctionalOnly() ? 128 : 1;
+ int max_speed = IsBenchmarkFunctionalOnly() ? 128 : 2;
+ for (int speed = min_speed; speed <= max_speed; speed *= 2) {
+ b->Args({2, speed});
+ b->Args({4, speed});
+ }
+}
+
} // namespace
-static void BM_EndToEnd_SaturateCpu(benchmark::State& state) {
- BenchmarkCommon(state);
+static void BM_EndToEnd_Producer_SaturateCpu(benchmark::State& state) {
+ BenchmarkProducer(state);
}
-BENCHMARK(BM_EndToEnd_SaturateCpu)
+BENCHMARK(BM_EndToEnd_Producer_SaturateCpu)
->Unit(benchmark::kMicrosecond)
->UseRealTime()
- ->Apply(SaturateCpuArgs);
+ ->Apply(SaturateCpuProducerArgs);
-static void BM_EndToEnd_ConstantRate(benchmark::State& state) {
- BenchmarkCommon(state);
+static void BM_EndToEnd_Producer_ConstantRate(benchmark::State& state) {
+ BenchmarkProducer(state);
}
-BENCHMARK(BM_EndToEnd_ConstantRate)
+BENCHMARK(BM_EndToEnd_Producer_ConstantRate)
->Unit(benchmark::kMicrosecond)
->UseRealTime()
- ->Apply(ConstantRateArgs);
+ ->Apply(ConstantRateProducerArgs);
+
+static void BM_EndToEnd_Consumer_SaturateCpu(benchmark::State& state) {
+ BenchmarkConsumer(state);
+}
+
+BENCHMARK(BM_EndToEnd_Consumer_SaturateCpu)
+ ->Unit(benchmark::kMicrosecond)
+ ->UseRealTime()
+ ->Apply(SaturateCpuConsumerArgs);
+
+static void BM_EndToEnd_Consumer_ConstantRate(benchmark::State& state) {
+ BenchmarkConsumer(state);
+}
+
+BENCHMARK(BM_EndToEnd_Consumer_ConstantRate)
+ ->Unit(benchmark::kMillisecond)
+ ->UseRealTime()
+ ->Apply(ConstantRateConsumerArgs);
+
} // namespace perfetto
diff --git a/test/fake_producer.cc b/test/fake_producer.cc
index f2922d6..823759c 100644
--- a/test/fake_producer.cc
+++ b/test/fake_producer.cc
@@ -107,11 +107,12 @@
handle->set_for_testing()->set_str(payload.get(), message_size_);
}
messages_to_emit -= messages_in_minibatch;
+ iterations++;
// Pause until the second boundary to make sure that we are adhering to
// the speed limitation.
if (max_messages_per_second_ > 0) {
- int64_t expected_time_taken = ++iterations * 1000;
+ int64_t expected_time_taken = iterations * 1000;
base::TimeMillis time_taken = base::GetWallTimeMs() - start;
while (time_taken.count() < expected_time_taken) {
usleep(static_cast<useconds_t>(
@@ -119,8 +120,8 @@
time_taken = base::GetWallTimeMs() - start;
}
}
+ trace_writer_->Flush(messages_to_emit > 0 ? [] {} : callback);
}
- trace_writer_->Flush(callback);
});
}
diff --git a/test/test_helper.cc b/test/test_helper.cc
index e5b78c9..55fa082 100644
--- a/test/test_helper.cc
+++ b/test/test_helper.cc
@@ -100,9 +100,9 @@
endpoint_->EnableTracing(config);
}
-void TestHelper::ReadData() {
- on_packets_finished_callback_ =
- task_runner_->CreateCheckpoint("readback.complete");
+void TestHelper::ReadData(uint32_t read_count) {
+ on_packets_finished_callback_ = task_runner_->CreateCheckpoint(
+ "readback.complete." + std::to_string(read_count));
endpoint_->ReadBuffers();
}
@@ -118,8 +118,9 @@
task_runner_->RunUntilCheckpoint("stop.tracing");
}
-void TestHelper::WaitForReadData() {
- task_runner_->RunUntilCheckpoint("readback.complete");
+void TestHelper::WaitForReadData(uint32_t read_count) {
+ task_runner_->RunUntilCheckpoint("readback.complete." +
+ std::to_string(read_count));
}
std::function<void()> TestHelper::WrapTask(
diff --git a/test/test_helper.h b/test/test_helper.h
index b26a88d..d7afc86 100644
--- a/test/test_helper.h
+++ b/test/test_helper.h
@@ -43,12 +43,12 @@
FakeProducer* ConnectFakeProducer();
void ConnectConsumer();
void StartTracing(const TraceConfig& config);
- void ReadData();
+ void ReadData(uint32_t read_count = 0);
void WaitForConsumerConnect();
void WaitForProducerEnabled();
void WaitForTracingDisabled();
- void WaitForReadData();
+ void WaitForReadData(uint32_t read_count = 0);
std::function<void()> WrapTask(const std::function<void()>& function);
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen.cc b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
index 1d94101..3c7e228 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen.cc
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
@@ -16,12 +16,11 @@
#include "tools/ftrace_proto_gen/ftrace_proto_gen.h"
-#include "perfetto/base/string_splitter.h"
-
#include <fstream>
#include <regex>
-#include <set>
-#include <string>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/string_splitter.h"
namespace perfetto {
@@ -64,6 +63,64 @@
} // namespace
+ProtoType ProtoType::GetSigned() const {
+ PERFETTO_CHECK(type == NUMERIC);
+ if (is_signed)
+ return *this;
+
+ if (size == 64) {
+ return Numeric(64, true);
+ }
+
+ return Numeric(2 * size, true);
+}
+
+std::string ProtoType::ToString() const {
+ switch (type) {
+ case INVALID:
+ PERFETTO_CHECK(false);
+ case STRING:
+ return "string";
+ case NUMERIC: {
+ std::string s;
+ if (!is_signed)
+ s += "u";
+ s += "int";
+ s += std::to_string(size);
+ return s;
+ }
+ }
+ PERFETTO_CHECK(false); // for GCC.
+}
+
+// static
+ProtoType ProtoType::String() {
+ return {STRING, 0, false};
+}
+
+// static
+ProtoType ProtoType::Invalid() {
+ return {INVALID, 0, false};
+}
+
+// static
+ProtoType ProtoType::Numeric(uint16_t size, bool is_signed) {
+ PERFETTO_CHECK(size == 32 || size == 64);
+ return {NUMERIC, size, is_signed};
+}
+
+ProtoType GetCommon(ProtoType one, ProtoType other) {
+ if (one.type == ProtoType::STRING || other.type == ProtoType::STRING)
+ return ProtoType::String();
+
+ if (one.is_signed || other.is_signed) {
+ one = one.GetSigned();
+ other = other.GetSigned();
+ }
+
+ return ProtoType::Numeric(std::max(one.size, other.size), one.is_signed);
+}
+
std::vector<std::string> GetFileLines(const std::string& filename) {
std::string line;
std::vector<std::string> lines;
@@ -80,44 +137,40 @@
return lines;
}
-std::string InferProtoType(const FtraceEvent::Field& field) {
+ProtoType InferProtoType(const FtraceEvent::Field& field) {
// Fixed length strings: "char foo[16]"
if (std::regex_match(field.type_and_name, std::regex(R"(char \w+\[\d+\])")))
- return "string";
+ return ProtoType::String();
// String pointers: "__data_loc char[] foo" (as in
// 'cpufreq_interactive_boost').
if (Contains(field.type_and_name, "char[] "))
- return "string";
+ return ProtoType::String();
if (Contains(field.type_and_name, "char * "))
- return "string";
+ return ProtoType::String();
// Variable length strings: "char* foo"
if (StartsWith(field.type_and_name, "char *"))
- return "string";
+ return ProtoType::String();
// Variable length strings: "char foo" + size: 0 (as in 'print').
if (StartsWith(field.type_and_name, "char ") && field.size == 0)
- return "string";
+ return ProtoType::String();
// ino_t, i_ino and dev_t are 32bit on some devices 64bit on others. For the
// protos we need to choose the largest possible size.
if (StartsWith(field.type_and_name, "ino_t ") ||
StartsWith(field.type_and_name, "i_ino ") ||
StartsWith(field.type_and_name, "dev_t ")) {
- return "uint64";
+ return ProtoType::Numeric(64, /* is_signed= */ false);
}
// Ints of various sizes:
- if (field.size <= 4 && field.is_signed)
- return "int32";
- if (field.size <= 4 && !field.is_signed)
- return "uint32";
- if (field.size <= 8 && field.is_signed)
- return "int64";
- if (field.size <= 8 && !field.is_signed)
- return "uint64";
- return "";
+ if (field.size <= 4)
+ return ProtoType::Numeric(32, field.is_signed);
+ if (field.size <= 8)
+ return ProtoType::Numeric(64, field.is_signed);
+ return ProtoType::Invalid();
}
void PrintEventFormatterMain(const std::set<std::string>& events) {
@@ -177,11 +230,12 @@
if (name == "" || seen.count(name))
continue;
seen.insert(name);
- std::string type = InferProtoType(field);
+ ProtoType type = InferProtoType(field);
// Check we managed to infer a type.
- if (type == "")
+ if (type.type == ProtoType::INVALID)
continue;
- proto_out->fields.emplace_back(Proto::Field{type, name, i});
+ proto_out->fields.emplace_back(
+ Proto::Field{std::move(type), std::move(name), i});
i++;
}
@@ -260,8 +314,8 @@
for (const auto& field : proto.fields) {
s += " event->fields.push_back(MakeField(\"" + field.name + "\", " +
- std::to_string(field.number) + ", kProto" + ToCamelCase(field.type) +
- "));\n";
+ std::to_string(field.number) + ", kProto" +
+ ToCamelCase(field.type.ToString()) + "));\n";
}
return s;
}
@@ -321,7 +375,7 @@
s += "message " + name + " {\n";
for (const Proto::Field& field : fields) {
- s += " optional " + field.type + " " + field.name + " = " +
+ s += " optional " + field.type.ToString() + " " + field.name + " = " +
std::to_string(field.number) + ";\n";
}
s += "}\n";
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen.h b/tools/ftrace_proto_gen/ftrace_proto_gen.h
index 86e834b..f0c9a38 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen.h
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen.h
@@ -25,9 +25,23 @@
namespace perfetto {
+struct ProtoType {
+ enum Type { INVALID, NUMERIC, STRING };
+ Type type;
+ uint16_t size;
+ bool is_signed;
+
+ ProtoType GetSigned() const;
+ std::string ToString() const;
+
+ static ProtoType Invalid();
+ static ProtoType String();
+ static ProtoType Numeric(uint16_t size, bool is_signed);
+};
+
struct Proto {
struct Field {
- std::string type;
+ ProtoType type;
std::string name;
uint32_t number;
};
@@ -37,6 +51,7 @@
std::string ToString();
};
+ProtoType GetCommon(ProtoType one, ProtoType other);
void PrintFtraceEventProtoAdditions(const std::set<std::string>& events);
void PrintEventFormatterMain(const std::set<std::string>& events);
void PrintEventFormatterUsingStatements(const std::set<std::string>& events);
@@ -45,7 +60,7 @@
const perfetto::Proto& proto);
bool GenerateProto(const FtraceEvent& format, Proto* proto_out);
-std::string InferProtoType(const FtraceEvent::Field& field);
+ProtoType InferProtoType(const FtraceEvent::Field& field);
std::vector<std::string> GetFileLines(const std::string& filename);
std::set<std::string> GetWhitelistedEvents(
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen_unittest.cc b/tools/ftrace_proto_gen/ftrace_proto_gen_unittest.cc
index 943f133..8943e7b 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen_unittest.cc
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen_unittest.cc
@@ -22,26 +22,39 @@
TEST(FtraceEventParserTest, InferProtoType) {
using Field = FtraceEvent::Field;
- EXPECT_EQ(InferProtoType(Field{"char foo[16]", 0, 16, false}), "string");
- EXPECT_EQ(InferProtoType(Field{"char bar_42[64]", 0, 64, false}), "string");
- EXPECT_EQ(InferProtoType(Field{"__data_loc char[] foo", 0, 4, false}),
+ EXPECT_EQ(InferProtoType(Field{"char foo[16]", 0, 16, false}).ToString(),
"string");
- EXPECT_EQ(InferProtoType(Field{"char[] foo", 0, 8, false}), "string");
- EXPECT_EQ(InferProtoType(Field{"char * foo", 0, 8, false}), "string");
+ EXPECT_EQ(InferProtoType(Field{"char bar_42[64]", 0, 64, false}).ToString(),
+ "string");
+ EXPECT_EQ(
+ InferProtoType(Field{"__data_loc char[] foo", 0, 4, false}).ToString(),
+ "string");
+ EXPECT_EQ(InferProtoType(Field{"char[] foo", 0, 8, false}).ToString(),
+ "string");
+ EXPECT_EQ(InferProtoType(Field{"char * foo", 0, 8, false}).ToString(),
+ "string");
- EXPECT_EQ(InferProtoType(Field{"int foo", 0, 4, true}), "int32");
- EXPECT_EQ(InferProtoType(Field{"s32 signal", 50, 4, true}), "int32");
+ EXPECT_EQ(InferProtoType(Field{"int foo", 0, 4, true}).ToString(), "int32");
+ EXPECT_EQ(InferProtoType(Field{"s32 signal", 50, 4, true}).ToString(),
+ "int32");
- EXPECT_EQ(InferProtoType(Field{"unsigned int foo", 0, 4, false}), "uint32");
- EXPECT_EQ(InferProtoType(Field{"u32 control_freq", 44, 4, false}), "uint32");
+ EXPECT_EQ(InferProtoType(Field{"unsigned int foo", 0, 4, false}).ToString(),
+ "uint32");
+ EXPECT_EQ(InferProtoType(Field{"u32 control_freq", 44, 4, false}).ToString(),
+ "uint32");
- EXPECT_EQ(InferProtoType(Field{"ino_t foo", 0, 4, false}), "uint64");
- EXPECT_EQ(InferProtoType(Field{"ino_t foo", 0, 8, false}), "uint64");
+ EXPECT_EQ(InferProtoType(Field{"ino_t foo", 0, 4, false}).ToString(),
+ "uint64");
+ EXPECT_EQ(InferProtoType(Field{"ino_t foo", 0, 8, false}).ToString(),
+ "uint64");
- EXPECT_EQ(InferProtoType(Field{"dev_t foo", 0, 4, false}), "uint64");
- EXPECT_EQ(InferProtoType(Field{"dev_t foo", 0, 8, false}), "uint64");
+ EXPECT_EQ(InferProtoType(Field{"dev_t foo", 0, 4, false}).ToString(),
+ "uint64");
+ EXPECT_EQ(InferProtoType(Field{"dev_t foo", 0, 8, false}).ToString(),
+ "uint64");
- EXPECT_EQ(InferProtoType(Field{"char foo", 0, 0, false}), "string");
+ EXPECT_EQ(InferProtoType(Field{"char foo", 0, 0, false}).ToString(),
+ "string");
}
TEST(FtraceEventParserTest, GenerateProtoName) {
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index f71e001..d887501 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -368,6 +368,7 @@
parser.add_argument('--cpp_out')
parser.add_argument('--plugin')
parser.add_argument('--plugin_out')
+ parser.add_argument('--descriptor_set_out')
parser.add_argument('protos', nargs=argparse.REMAINDER)
args = parser.parse_args(args[1:])