Merge "tools: allow specifying a different origin for open_trace_in_ui"
diff --git a/include/perfetto/tracing/data_source.h b/include/perfetto/tracing/data_source.h
index 5581e34..5f69d39 100644
--- a/include/perfetto/tracing/data_source.h
+++ b/include/perfetto/tracing/data_source.h
@@ -121,6 +121,13 @@
uint32_t internal_instance_index = 0;
};
virtual void OnStop(const StopArgs&);
+
+ class ClearIncrementalStateArgs {
+ public:
+ // The index of this data source instance (0..kMaxDataSourceInstances - 1).
+ uint32_t internal_instance_index = 0;
+ };
+ virtual void WillClearIncrementalState(const ClearIncrementalStateArgs&);
};
struct DefaultDataSourceTraits {
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
index 8a3f331..ce2e0f0 100644
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ b/include/perfetto/tracing/internal/track_event_data_source.h
@@ -206,6 +206,11 @@
TrackEventInternal::DisableTracing(*Registry, args);
}
+ void WillClearIncrementalState(
+ const DataSourceBase::ClearIncrementalStateArgs& args) override {
+ TrackEventInternal::WillClearIncrementalState(args);
+ }
+
static void Flush() {
Base::template Trace([](typename Base::TraceContext ctx) { ctx.Flush(); });
}
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index 4fc3ce3..00aa3f5 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -78,6 +78,9 @@
// Called when a track event tracing session is stopped. It is still possible
// to emit track events from this callback.
virtual void OnStop(const DataSourceBase::StopArgs&);
+ // Called when tracing muxer requests to clear incremental state.
+ virtual void WillClearIncrementalState(
+ const DataSourceBase::ClearIncrementalStateArgs&);
};
namespace internal {
@@ -179,6 +182,9 @@
static void OnStart(const DataSourceBase::StartArgs&);
static void DisableTracing(const TrackEventCategoryRegistry& registry,
const DataSourceBase::StopArgs&);
+ static void WillClearIncrementalState(
+ const DataSourceBase::ClearIncrementalStateArgs&);
+
static bool IsCategoryEnabled(const TrackEventCategoryRegistry& registry,
const protos::gen::TrackEventConfig& config,
const Category& category);
diff --git a/protos/third_party/chromium/chrome_track_event.proto b/protos/third_party/chromium/chrome_track_event.proto
index b09dbac..fbaf9f9 100644
--- a/protos/third_party/chromium/chrome_track_event.proto
+++ b/protos/third_party/chromium/chrome_track_event.proto
@@ -779,9 +779,15 @@
DEVICE_THERMAL_STATE_CRITICAL = 4;
}
+// Used to log which Android IPC was called and how long it took.
+message AndroidIPC {
+ optional string name = 1;
+ optional int64 dur_ms = 2;
+}
+
message ChromeTrackEvent {
// Extension range for Chrome: 1000-1999
- // Next ID: 1037
+ // Next ID: 1039
extend TrackEvent {
optional ChromeAppState chrome_app_state = 1000;
@@ -863,5 +869,7 @@
optional DeviceThermalState device_thermal_state = 1036;
optional NavigationHandle navigation = 1037;
+
+ optional AndroidIPC android_ipc = 1038;
}
}
diff --git a/src/trace_processor/importers/proto/atoms.descriptor b/src/trace_processor/importers/proto/atoms.descriptor
index a905e16..4c52406 100644
--- a/src/trace_processor/importers/proto/atoms.descriptor
+++ b/src/trace_processor/importers/proto/atoms.descriptor
Binary files differ
diff --git a/src/trace_processor/sqlite/create_function.cc b/src/trace_processor/sqlite/create_function.cc
index 8aa5f92..eee35e7 100644
--- a/src/trace_processor/sqlite/create_function.cc
+++ b/src/trace_processor/sqlite/create_function.cc
@@ -43,7 +43,8 @@
sqlite3_value** argv,
SqlValue& out,
Destructors&);
- static base::Status Cleanup(Context*);
+ static base::Status VerifyPostConditions(Context*);
+ static void Cleanup(Context*);
};
base::Status CreatedFunction::Run(CreatedFunction::Context* ctx,
@@ -117,7 +118,7 @@
return base::OkStatus();
}
-base::Status CreatedFunction::Cleanup(CreatedFunction::Context* ctx) {
+base::Status CreatedFunction::VerifyPostConditions(Context* ctx) {
int ret = sqlite3_step(ctx->stmt);
RETURN_IF_ERROR(
SqliteRetToStatus(ctx->db, ctx->prototype.function_name, ret));
@@ -128,16 +129,14 @@
ctx->prototype.function_name.c_str(), sqlite3_expanded_sql(ctx->stmt));
}
PERFETTO_DCHECK(ret == SQLITE_DONE);
-
- // Make sure to reset the statement to remove any bindings.
- ret = sqlite3_reset(ctx->stmt);
- if (ret != SQLITE_OK) {
- return base::ErrStatus("%s: error while resetting metric",
- ctx->prototype.function_name.c_str());
- }
return base::OkStatus();
}
+void CreatedFunction::Cleanup(CreatedFunction::Context* ctx) {
+ sqlite3_reset(ctx->stmt);
+ sqlite3_clear_bindings(ctx->stmt);
+}
+
} // namespace
size_t CreateFunction::NameAndArgc::Hasher::operator()(
diff --git a/src/trace_processor/sqlite/register_function.cc b/src/trace_processor/sqlite/register_function.cc
index 431e4d6..88216bd 100644
--- a/src/trace_processor/sqlite/register_function.cc
+++ b/src/trace_processor/sqlite/register_function.cc
@@ -21,9 +21,11 @@
namespace perfetto {
namespace trace_processor {
-base::Status SqlFunction::Cleanup(Context*) {
+base::Status SqlFunction::VerifyPostConditions(Context*) {
return base::OkStatus();
}
+void SqlFunction::Cleanup(Context*) {}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/sqlite/register_function.h b/src/trace_processor/sqlite/register_function.h
index 1761af4..95c24cd 100644
--- a/src/trace_processor/sqlite/register_function.h
+++ b/src/trace_processor/sqlite/register_function.h
@@ -78,11 +78,20 @@
Destructors& destructors);
// Executed after the result from |Run| is reported to SQLite.
- // Allows any pending state to be cleaned up post-copy of results by SQLite.
+ // Allows implementations to verify post-conditions without needing to worry
+ // about overwriting return types.
//
// Implementations do not need to define this function; a default no-op
// implementation will be used in this case.
- static base::Status Cleanup(Context*);
+ static base::Status VerifyPostConditions(Context*);
+
+ // Executed after the result from |Run| is reported to SQLite.
+ // Allows any pending state to be cleaned up post-copy of results by SQLite:
+ // this function will be called even if |Run| or |PostRun| returned errors.
+ //
+ // Implementations do not need to define this function; a default no-op
+ // implementation will be used in this case.
+ static void Cleanup(Context*);
};
// Registers a C++ function to be runnable from SQL.
@@ -126,24 +135,33 @@
namespace trace_processor {
namespace sqlite_internal {
+
+// RAII type to call Function::Cleanup when destroyed.
+template <typename Function>
+struct ScopedCleanup {
+ typename Function::Context* ctx;
+ ~ScopedCleanup() { Function::Cleanup(ctx); }
+};
+
template <typename Function>
void WrapSqlFunction(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
using Context = typename Function::Context;
- auto* ud = static_cast<Context*>(sqlite3_user_data(ctx));
+ Context* ud = static_cast<Context*>(sqlite3_user_data(ctx));
+ ScopedCleanup<Function> scoped_cleanup{ud};
SqlValue value{};
SqlFunction::Destructors destructors{};
base::Status status =
Function::Run(ud, static_cast<size_t>(argc), argv, value, destructors);
-
if (!status.ok()) {
sqlite3_result_error(ctx, status.c_message(), -1);
return;
}
+
sqlite_utils::ReportSqlValue(ctx, value, destructors.string_destructor,
destructors.bytes_destructor);
- status = Function::Cleanup(ud);
+ status = Function::VerifyPostConditions(ud);
if (!status.ok()) {
sqlite3_result_error(ctx, status.c_message(), -1);
return;
diff --git a/src/tracing/data_source.cc b/src/tracing/data_source.cc
index 418ba43..0f4a5d1 100644
--- a/src/tracing/data_source.cc
+++ b/src/tracing/data_source.cc
@@ -23,5 +23,7 @@
void DataSourceBase::OnSetup(const SetupArgs&) {}
void DataSourceBase::OnStart(const StartArgs&) {}
void DataSourceBase::OnStop(const StopArgs&) {}
+void DataSourceBase::WillClearIncrementalState(
+ const ClearIncrementalStateArgs&) {}
} // namespace perfetto
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
index dd34ca4..7f46a3a 100644
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ b/src/tracing/internal/tracing_muxer_impl.cc
@@ -1116,6 +1116,16 @@
PERFETTO_ELOG("Could not find data source to clear incremental state for");
return;
}
+
+ DataSourceBase::ClearIncrementalStateArgs clear_incremental_state_args;
+ clear_incremental_state_args.internal_instance_index = ds.instance_idx;
+
+ {
+ std::lock_guard<std::recursive_mutex> guard(ds.internal_state->lock);
+ ds.internal_state->data_source->WillClearIncrementalState(
+ clear_incremental_state_args);
+ }
+
// Make DataSource::TraceContext::GetIncrementalState() eventually notice that
// the incremental state should be cleared.
ds.static_state->incremental_state_generation.fetch_add(
diff --git a/src/tracing/internal/track_event_internal.cc b/src/tracing/internal/track_event_internal.cc
index 27ca5bf..b07f498 100644
--- a/src/tracing/internal/track_event_internal.cc
+++ b/src/tracing/internal/track_event_internal.cc
@@ -40,6 +40,8 @@
void TrackEventSessionObserver::OnSetup(const DataSourceBase::SetupArgs&) {}
void TrackEventSessionObserver::OnStart(const DataSourceBase::StartArgs&) {}
void TrackEventSessionObserver::OnStop(const DataSourceBase::StopArgs&) {}
+void TrackEventSessionObserver::WillClearIncrementalState(
+ const DataSourceBase::ClearIncrementalStateArgs&) {}
namespace internal {
@@ -205,6 +207,16 @@
}
// static
+void TrackEventInternal::WillClearIncrementalState(
+ const DataSourceBase::ClearIncrementalStateArgs& args) {
+ ForEachObserver([&](TrackEventSessionObserver*& o) {
+ if (o)
+ o->WillClearIncrementalState(args);
+ return true;
+ });
+}
+
+// static
bool TrackEventInternal::IsCategoryEnabled(
const TrackEventCategoryRegistry& registry,
const protos::gen::TrackEventConfig& config,
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index 13329c1..828f2f4 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -535,8 +535,8 @@
TestTracingSessionHandle* NewTraceWithCategories(
std::vector<std::string> categories,
- perfetto::protos::gen::TrackEventConfig te_cfg = {}) {
- perfetto::TraceConfig cfg;
+ perfetto::protos::gen::TrackEventConfig te_cfg = {},
+ perfetto::TraceConfig cfg = {}) {
cfg.set_duration_ms(500);
cfg.add_buffers()->set_size_kb(1024);
auto* ds_cfg = cfg.add_data_sources()->mutable_config();
@@ -4870,6 +4870,52 @@
EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
}
+TEST_P(PerfettoApiTest, TrackEventObserver_ClearIncrementalState) {
+ class Observer : public perfetto::TrackEventSessionObserver {
+ public:
+ ~Observer() override = default;
+
+ void OnStart(const perfetto::DataSourceBase::StartArgs&) {
+ EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
+ EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
+ TRACE_EVENT_INSTANT("foo", "OnStart");
+ }
+
+ void WillClearIncrementalState(
+ const perfetto::DataSourceBase::ClearIncrementalStateArgs&) {
+ if (clear_incremental_state_called)
+ return;
+ clear_incremental_state_called = true;
+ EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
+ EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
+ TRACE_EVENT_INSTANT("foo", "WillClearIncrementalState");
+ perfetto::TrackEvent::Flush();
+ }
+
+ bool clear_incremental_state_called{};
+ };
+
+ EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
+ {
+ Observer observer;
+ perfetto::TrackEvent::AddSessionObserver(&observer);
+
+ perfetto::TraceConfig cfg;
+ cfg.mutable_incremental_state_config()->set_clear_period_ms(100);
+ auto* tracing_session = NewTraceWithCategories({"foo"}, {}, cfg);
+
+ tracing_session->get()->StartBlocking();
+ tracing_session->on_stop.Wait();
+
+ EXPECT_TRUE(observer.clear_incremental_state_called);
+ perfetto::TrackEvent::RemoveSessionObserver(&observer);
+ auto slices = ReadSlicesFromTrace(tracing_session->get());
+ EXPECT_THAT(slices, ElementsAre("I:foo.OnStart",
+ "I:foo.WillClearIncrementalState"));
+ }
+ EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
+}
+
#if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_CLANG)
struct __attribute__((capability("mutex"))) MockMutex {
void Lock() __attribute__((acquire_capability())) {}
diff --git a/test/cts/reporter/AndroidManifest.xml b/test/cts/reporter/AndroidManifest.xml
index 9a2ef40..51681d8 100755
--- a/test/cts/reporter/AndroidManifest.xml
+++ b/test/cts/reporter/AndroidManifest.xml
@@ -19,7 +19,6 @@
package="android.perfetto.cts.reporter">
<uses-permission android:name="android.permission.DUMP"/>
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
-1
<application>
<service
android:name=".PerfettoReportService"
diff --git a/tools/update-statsd-descriptor b/tools/update-statsd-descriptor
index a4d47a8..a038d6d 100755
--- a/tools/update-statsd-descriptor
+++ b/tools/update-statsd-descriptor
@@ -58,6 +58,7 @@
f"--proto_path={PROTOBUF_BUILTINS_DIR}",
f"--proto_path={tmpdir}",
f"--descriptor_set_out={DESCRIPTOR_PATH}",
+ "--include_imports",
atoms_path)
diff --git a/ui/src/controller/track_decider.ts b/ui/src/controller/track_decider.ts
index 4bd8445..b4f5faa 100644
--- a/ui/src/controller/track_decider.ts
+++ b/ui/src/controller/track_decider.ts
@@ -1286,6 +1286,18 @@
join thread on process.upid = thread.upid
join perf_sample on thread.utid = perf_sample.utid
) using (upid)
+ left join (
+ select
+ process.upid as upid,
+ count(*) as sliceCount
+ from process
+ join thread on process.upid = thread.upid
+ join thread_track on thread_track.utid = thread.utid
+ join process_track on process_track.upid = process.upid
+ join slices on slices.track_id = thread_track.id
+ or slices.track_id = process_track.id
+ group by process.upid
+ ) using (upid)
left join thread using(utid)
left join process using(upid)
order by
@@ -1293,6 +1305,7 @@
hasHeapProfiles desc,
perfSampleCount desc,
total_dur desc,
+ sliceCount desc,
processName,
the_tracks.upid,
threadName,