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,