Merge "tp: CPU state breakdowns" into main
diff --git a/include/perfetto/ext/base/sys_types.h b/include/perfetto/ext/base/sys_types.h
index 49eeb11..cbb085d 100644
--- a/include/perfetto/ext/base/sys_types.h
+++ b/include/perfetto/ext/base/sys_types.h
@@ -41,6 +41,11 @@
 
 #endif  // OS_WIN
 
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && !defined(AID_SHELL)
+// From libcutils' android_filesystem_config.h .
+#define AID_SHELL 2000
+#endif
+
 namespace perfetto {
 namespace base {
 
diff --git a/src/tracing/service/tracing_service_impl.cc b/src/tracing/service/tracing_service_impl.cc
index b57f135..5e12b22 100644
--- a/src/tracing/service/tracing_service_impl.cc
+++ b/src/tracing/service/tracing_service_impl.cc
@@ -59,6 +59,7 @@
 #include "perfetto/ext/base/metatrace.h"
 #include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/string_view.h"
+#include "perfetto/ext/base/sys_types.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/ext/base/uuid.h"
 #include "perfetto/ext/base/version.h"
@@ -3939,8 +3940,7 @@
   // Skip the UID check for sessions marked with a bugreport_score > 0.
   // Those sessions, by design, can be stolen by any other consumer for the
   // sake of creating snapshots for bugreports.
-  if (src->config.bugreport_score() <= 0 &&
-      src->consumer_uid != consumer->uid_ && consumer->uid_ != 0) {
+  if (!src->IsCloneAllowed(consumer->uid_)) {
     return PERFETTO_SVC_ERR("Not allowed to clone a session from another UID");
   }
 
@@ -4028,6 +4028,20 @@
   return base::OkStatus();
 }
 
+bool TracingServiceImpl::TracingSession::IsCloneAllowed(uid_t clone_uid) const {
+  if (clone_uid == 0)
+    return true;  // Root is always allowed to clone everything.
+  if (clone_uid == this->consumer_uid)
+    return true;  // Allow cloning if the uids match.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+  // On Android allow shell to clone sessions marked as exported for bugreport.
+  // Dumpstate (invoked by adb bugreport) invokes commands as shell.
+  if (clone_uid == AID_SHELL && this->config.bugreport_score() > 0)
+    return true;
+#endif
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // TracingServiceImpl::ConsumerEndpointImpl implementation
 ////////////////////////////////////////////////////////////////////////////////
@@ -4298,8 +4312,7 @@
   svc_state.set_supports_tracing_sessions(true);
   for (const auto& kv : service_->tracing_sessions_) {
     const TracingSession& s = kv.second;
-    // List only tracing sessions for the calling UID (or everything for root).
-    if (uid_ != 0 && uid_ != s.consumer_uid)
+    if (!s.IsCloneAllowed(uid_))
       continue;
     auto* session = svc_state.add_tracing_sessions();
     session->set_id(s.id);
diff --git a/src/tracing/service/tracing_service_impl.h b/src/tracing/service/tracing_service_impl.h
index a20fa68..8dd2985 100644
--- a/src/tracing/service/tracing_service_impl.h
+++ b/src/tracing/service/tracing_service_impl.h
@@ -573,6 +573,10 @@
           });
     }
 
+    // Checks whether |clone_uid| is allowed to clone the current tracing
+    // session.
+    bool IsCloneAllowed(uid_t clone_uid) const;
+
     const TracingSessionID id;
 
     // The consumer that started the session.
diff --git a/src/tracing/service/tracing_service_impl_unittest.cc b/src/tracing/service/tracing_service_impl_unittest.cc
index 8193bb6..9e54d57 100644
--- a/src/tracing/service/tracing_service_impl_unittest.cc
+++ b/src/tracing/service/tracing_service_impl_unittest.cc
@@ -20,6 +20,7 @@
 
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/string_utils.h"
+#include "perfetto/ext/base/sys_types.h"
 #include "perfetto/ext/base/temp_file.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/ext/tracing/core/client_identity.h"
@@ -4912,8 +4913,9 @@
   task_runner.RunUntilCheckpoint("clone_done");
 }
 
-// Test that a consumer can clone a session from a different uid if the trace is
-// marked as eligible for bugreport.
+// Test that a consumer can clone a session from the shell uid if the trace is
+// marked as eligible for bugreport. Android only.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
 TEST_F(TracingServiceImplTest, CloneSessionAcrossUidForBugreport) {
   // The consumer the creates the initial tracing session.
   std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
@@ -4925,7 +4927,7 @@
 
   // The consumer that clones it and reads back the data.
   std::unique_ptr<MockConsumer> clone_consumer = CreateMockConsumer();
-  clone_consumer->Connect(svc.get(), 1234);
+  clone_consumer->Connect(svc.get(), AID_SHELL);
 
   TraceConfig trace_config;
   trace_config.add_buffers()->set_size_kb(32);
@@ -4976,6 +4978,7 @@
                                          Property(&protos::gen::TestEvent::str,
                                                   HasSubstr("payload")))));
 }
+#endif  // OS_ANDROID
 
 TEST_F(TracingServiceImplTest, TransferOnClone) {
   // The consumer the creates the initial tracing session.