1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SRC_PERFETTO_CMD_PERFETTO_CMD_H_ 18 #define SRC_PERFETTO_CMD_PERFETTO_CMD_H_ 19 20 #include <cstdint> 21 #include <functional> 22 #include <list> 23 #include <memory> 24 #include <optional> 25 #include <string> 26 #include <vector> 27 28 #include "perfetto/base/build_config.h" 29 #include "perfetto/ext/base/event_fd.h" 30 #include "perfetto/ext/base/pipe.h" 31 #include "perfetto/ext/base/scoped_file.h" 32 #include "perfetto/ext/base/thread_task_runner.h" 33 #include "perfetto/ext/base/unix_task_runner.h" 34 #include "perfetto/ext/base/uuid.h" 35 #include "perfetto/ext/base/weak_ptr.h" 36 #include "perfetto/ext/tracing/core/basic_types.h" 37 #include "perfetto/ext/tracing/core/consumer.h" 38 #include "perfetto/ext/tracing/ipc/consumer_ipc_client.h" 39 #include "perfetto/tracing/core/forward_decls.h" 40 #include "src/android_stats/perfetto_atoms.h" 41 #include "src/perfetto_cmd/packet_writer.h" 42 43 namespace perfetto { 44 45 // Directory for local state and temporary files. This is automatically 46 // created by the system by setting setprop persist.traced.enable=1. 47 extern const char* kStateDir; 48 49 class PerfettoCmd : public Consumer { 50 public: 51 PerfettoCmd(); 52 ~PerfettoCmd() override; 53 54 // The main() is split in two stages: cmdline parsing and actual interaction 55 // with traced. This is to allow tools like tracebox to avoid spawning the 56 // service for no reason if the cmdline parsing fails. 57 // Return value: 58 // std::nullopt: no error, the caller should call 59 // ConnectToServiceRunAndMaybeNotify. 60 // 0-N: the caller should exit() with the given exit code. 61 std::optional<int> ParseCmdlineAndMaybeDaemonize(int argc, char** argv); 62 int ConnectToServiceRunAndMaybeNotify(); 63 64 // perfetto::Consumer implementation. 65 void OnConnect() override; 66 void OnDisconnect() override; 67 void OnTracingDisabled(const std::string& error) override; 68 void OnTraceData(std::vector<TracePacket>, bool has_more) override; 69 void OnDetach(bool) override; 70 void OnAttach(bool, const TraceConfig&) override; 71 void OnTraceStats(bool, const TraceStats&) override; 72 void OnObservableEvents(const ObservableEvents&) override; 73 void OnSessionCloned(const OnSessionClonedArgs&) override; 74 SignalCtrlC()75 void SignalCtrlC() { ctrl_c_evt_.Notify(); } 76 77 private: 78 struct SnapshotTriggerInfo; 79 80 enum CloneThreadMode { kSingleExtraThread, kNewThreadPerRequest }; 81 82 bool OpenOutputFile(); 83 void SetupCtrlCSignalHandler(); 84 void FinalizeTraceAndExit(); 85 void PrintUsage(const char* argv0); 86 void PrintServiceState(bool success, const TracingServiceState&); 87 void CloneAllBugreportTraces(bool success, const TracingServiceState&); 88 89 void CloneSessionOnThread(TracingSessionID, 90 const std::string& cmdline, // \0 separated. 91 CloneThreadMode, 92 const std::optional<SnapshotTriggerInfo>& trigger, 93 std::function<void()> on_clone_callback); 94 void OnTimeout(); is_detach()95 bool is_detach() const { return !detach_key_.empty(); } is_attach()96 bool is_attach() const { return !attach_key_.empty(); } is_clone()97 bool is_clone() const { 98 return clone_tsid_.has_value() || !clone_name_.empty(); 99 } 100 101 // Once we call ReadBuffers we expect one or more calls to OnTraceData 102 // with the last call having |has_more| set to false. However we should 103 // gracefully handle the service failing to ever call OnTraceData or 104 // setting |has_more| incorrectly. To do this we maintain a timeout 105 // which finalizes and exits the client if we don't receive OnTraceData 106 // within OnTraceDataTimeoutMs of when we expected to. 107 void CheckTraceDataTimeout(); 108 109 int ConnectToServiceAndRun(); 110 111 void ReadbackTraceDataAndQuit(const std::string& error); 112 113 enum BgProcessStatus : char { 114 kBackgroundOk = 0, 115 kBackgroundOtherError = 1, 116 kBackgroundTimeout = 2, 117 }; 118 119 // Used to implement the --background-wait flag. 120 // 121 // Waits (up to 30s) for the child process to signal (success or an error). 122 // 123 // Returns the status received from the child process or kTimeout, in case of 124 // timeout. 125 BgProcessStatus WaitOnBgProcessPipe(); 126 127 // Used to implement the --background-wait flag. 128 // 129 // Signals the parent process (if there is one) that it can exit (successfully 130 // or with an error). 131 // 132 // Only the first time this function is called is significant. Further calls 133 // will have no effect. 134 void NotifyBgProcessPipe(BgProcessStatus status); 135 136 void OnCloneSnapshotTriggerReceived(TracingSessionID, 137 const SnapshotTriggerInfo& trigger); 138 139 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 140 static base::ScopedFile CreateUnlinkedTmpFile(); 141 void SaveTraceIntoIncidentOrCrash(); 142 void SaveOutputToIncidentTraceOrCrash(); 143 void ReportTraceToAndroidFrameworkOrCrash(); 144 #endif 145 void LogUploadEvent(PerfettoStatsdAtom atom); 146 void LogUploadEvent(PerfettoStatsdAtom atom, const std::string& trigger_name); 147 void LogTriggerEvents(PerfettoTriggerAtom atom, 148 const std::vector<std::string>& trigger_names); 149 150 base::UnixTaskRunner task_runner_; 151 152 std::unique_ptr<perfetto::TracingService::ConsumerEndpoint> 153 consumer_endpoint_; 154 std::unique_ptr<TraceConfig> trace_config_; 155 std::optional<PacketWriter> packet_writer_; 156 base::ScopedFstream trace_out_stream_; 157 std::vector<std::string> triggers_to_activate_; 158 std::string trace_out_path_; 159 base::EventFd ctrl_c_evt_; 160 bool ctrl_c_handler_installed_ = false; 161 base::Pipe background_wait_pipe_; 162 bool save_to_incidentd_ = false; 163 bool report_to_android_framework_ = false; 164 bool statsd_logging_ = false; 165 bool tracing_succeeded_ = false; 166 uint64_t bytes_written_ = 0; 167 std::string detach_key_; 168 std::string attach_key_; 169 bool stop_trace_once_attached_ = false; 170 bool redetach_once_attached_ = false; 171 bool query_service_ = false; 172 bool query_service_output_raw_ = false; 173 bool query_service_long_ = false; 174 bool clone_all_bugreport_traces_ = false; 175 bool bugreport_ = false; 176 bool background_ = false; 177 bool background_wait_ = false; 178 bool ignore_guardrails_ = false; 179 bool upload_flag_ = false; 180 bool connected_ = false; 181 std::string uuid_; 182 std::optional<TracingSessionID> clone_tsid_{}; 183 std::string clone_name_; 184 bool clone_for_bugreport_ = false; 185 std::function<void()> on_session_cloned_; 186 187 // How long we expect to trace for or 0 if the trace is indefinite. 188 uint32_t expected_duration_ms_ = 0; 189 bool trace_data_timeout_armed_ = false; 190 191 // The aux threads used to invoke secondary instances of PerfettoCmd to create 192 // snapshots. This is used only when the trace config involves a 193 // CLONE_SNAPSHOT trigger or when using --save-all-for-bugreport. 194 std::list<base::ThreadTaskRunner> snapshot_threads_; 195 int snapshot_count_ = 0; 196 std::string snapshot_config_; 197 // If the trigger caused the clone operation, we want to save the information 198 // about that trigger to the trace We may get multiple triggers with the same 199 // name, so we pass the entire structure to uniquely identify the trigger 200 // later. This structure is identical to the 201 // `TracingServiceImpl::TriggerInfo`. 202 struct SnapshotTriggerInfo { 203 uint64_t boot_time_ns = 0; 204 std::string trigger_name; 205 std::string producer_name; 206 uid_t producer_uid = 0; 207 }; 208 std::optional<SnapshotTriggerInfo> snapshot_trigger_info_; 209 210 base::WeakPtrFactory<PerfettoCmd> weak_factory_{this}; 211 }; 212 213 } // namespace perfetto 214 215 #endif // SRC_PERFETTO_CMD_PERFETTO_CMD_H_ 216