| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/bind.h" |
| #include "base/lazy_instance.h" |
| #include "base/memory/singleton.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "base/trace_event/trace_event_impl.h" |
| #include "content/browser/tracing/power_tracing_agent.h" |
| #include "tools/battor_agent/battor_finder.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| const char kPowerTracingAgentName[] = "battor"; |
| const char kPowerTraceLabel[] = "powerTraceAsString"; |
| |
| } // namespace |
| |
| // static |
| PowerTracingAgent* PowerTracingAgent::GetInstance() { |
| return base::Singleton<PowerTracingAgent>::get(); |
| } |
| |
| PowerTracingAgent::PowerTracingAgent() {} |
| PowerTracingAgent::~PowerTracingAgent() {} |
| |
| std::string PowerTracingAgent::GetTracingAgentName() { |
| return kPowerTracingAgentName; |
| } |
| |
| std::string PowerTracingAgent::GetTraceEventLabel() { |
| return kPowerTraceLabel; |
| } |
| |
| void PowerTracingAgent::StartAgentTracing( |
| const base::trace_event::TraceConfig& trace_config, |
| const StartAgentTracingCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| base::Bind(&PowerTracingAgent::FindBattOrOnFileThread, |
| base::Unretained(this), callback)); |
| } |
| |
| void PowerTracingAgent::FindBattOrOnFileThread( |
| const StartAgentTracingCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| |
| std::string path = battor::BattOrFinder::FindBattOr(); |
| if (path.empty()) { |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(callback, GetTracingAgentName(), false /* success */)); |
| return; |
| } |
| |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind(&PowerTracingAgent::StartAgentTracingOnIOThread, |
| base::Unretained(this), path, callback)); |
| } |
| |
| void PowerTracingAgent::StartAgentTracingOnIOThread( |
| const std::string& path, |
| const StartAgentTracingCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| |
| battor_agent_.reset(new battor::BattOrAgent( |
| path, this, BrowserThread::GetTaskRunnerForThread(BrowserThread::UI))); |
| |
| start_tracing_callback_ = callback; |
| battor_agent_->StartTracing(); |
| } |
| |
| void PowerTracingAgent::OnStartTracingComplete(battor::BattOrError error) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| |
| bool success = (error == battor::BATTOR_ERROR_NONE); |
| if (!success) |
| battor_agent_.reset(); |
| |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(start_tracing_callback_, GetTracingAgentName(), success)); |
| start_tracing_callback_.Reset(); |
| } |
| |
| void PowerTracingAgent::StopAgentTracing( |
| const StopAgentTracingCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind(&PowerTracingAgent::StopAgentTracingOnIOThread, |
| base::Unretained(this), callback)); |
| } |
| |
| void PowerTracingAgent::StopAgentTracingOnIOThread( |
| const StopAgentTracingCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| |
| if (!battor_agent_) { |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(callback, GetTracingAgentName(), GetTraceEventLabel(), |
| nullptr /* events_str_ptr */)); |
| return; |
| } |
| |
| stop_tracing_callback_ = callback; |
| battor_agent_->StopTracing(); |
| } |
| |
| void PowerTracingAgent::OnStopTracingComplete(const std::string& trace, |
| battor::BattOrError error) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| |
| scoped_refptr<base::RefCountedString> result(new base::RefCountedString()); |
| if (error == battor::BATTOR_ERROR_NONE) |
| result->data() = trace; |
| |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(stop_tracing_callback_, GetTracingAgentName(), |
| GetTraceEventLabel(), result)); |
| stop_tracing_callback_.Reset(); |
| battor_agent_.reset(); |
| } |
| |
| void PowerTracingAgent::RecordClockSyncMarker( |
| const std::string& sync_id, |
| const RecordClockSyncMarkerCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| DCHECK(SupportsExplicitClockSync()); |
| |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind(&PowerTracingAgent::RecordClockSyncMarkerOnIOThread, |
| base::Unretained(this), sync_id, callback)); |
| } |
| |
| void PowerTracingAgent::RecordClockSyncMarkerOnIOThread( |
| const std::string& sync_id, |
| const RecordClockSyncMarkerCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| DCHECK(battor_agent_); |
| |
| record_clock_sync_marker_sync_id_ = sync_id; |
| record_clock_sync_marker_callback_ = callback; |
| record_clock_sync_marker_start_time_ = base::TimeTicks::Now(); |
| battor_agent_->RecordClockSyncMarker(sync_id); |
| } |
| |
| void PowerTracingAgent::OnRecordClockSyncMarkerComplete( |
| battor::BattOrError error) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| |
| base::TimeTicks issue_start_ts = record_clock_sync_marker_start_time_; |
| base::TimeTicks issue_end_ts = base::TimeTicks::Now(); |
| |
| if (error != battor::BATTOR_ERROR_NONE) |
| issue_start_ts = issue_end_ts = base::TimeTicks(); |
| |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(record_clock_sync_marker_callback_, |
| record_clock_sync_marker_sync_id_, |
| issue_start_ts, |
| issue_end_ts)); |
| |
| record_clock_sync_marker_callback_.Reset(); |
| record_clock_sync_marker_sync_id_ = std::string(); |
| record_clock_sync_marker_start_time_ = base::TimeTicks(); |
| } |
| |
| bool PowerTracingAgent::SupportsExplicitClockSync() { |
| return battor_agent_->SupportsExplicitClockSync(); |
| } |
| |
| void PowerTracingAgent::OnGetFirmwareGitHashComplete( |
| const std::string& version, battor::BattOrError error) { |
| return; |
| } |
| |
| } // namespace content |