| // Copyright 2016 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 "chromeos/components/tether/hotspot_usage_duration_tracker.h" |
| |
| #include "base/metrics/histogram_macros.h" |
| #include "base/time/clock.h" |
| #include "chromeos/components/multidevice/logging/logging.h" |
| |
| namespace chromeos { |
| |
| namespace tether { |
| |
| namespace { |
| |
| // Minimum value for the usage duration metric. |
| const int64_t kMinDurationSeconds = 1; |
| |
| // Maximum value for the usage duration metric. |
| const int64_t kMaxDurationHours = 5; |
| |
| // Number of buckets in the metric. |
| const int kNumMetricsBuckets = 100; |
| |
| } // namespace |
| |
| HotspotUsageDurationTracker::HotspotUsageDurationTracker( |
| ActiveHost* active_host, |
| base::Clock* clock) |
| : active_host_(active_host), clock_(clock) { |
| active_host_->AddObserver(this); |
| } |
| |
| HotspotUsageDurationTracker::~HotspotUsageDurationTracker() { |
| active_host_->RemoveObserver(this); |
| } |
| |
| void HotspotUsageDurationTracker::OnActiveHostChanged( |
| const ActiveHost::ActiveHostChangeInfo& change_info) { |
| // Handle the case that a session is being tracked but the active host's |
| // status changes unexpectedly. |
| HandleUnexpectedCurrentSession(change_info.new_status); |
| |
| switch (change_info.new_status) { |
| case ActiveHost::ActiveHostStatus::CONNECTED: |
| last_connection_start_ = clock_->Now(); |
| break; |
| case ActiveHost::ActiveHostStatus::DISCONNECTED: { |
| // If |last_connection_start_| has not been set, there was no active |
| // connection before this status change; thus, there is nothing to do. |
| if (last_connection_start_.is_null()) |
| break; |
| |
| base::TimeDelta duration = clock_->Now() - last_connection_start_; |
| |
| // Reset |last_connection_start_|; it will be set again the next time that |
| // a connection is established. |
| last_connection_start_ = base::Time(); |
| |
| PA_LOG(VERBOSE) << "Connection to hotspot has ended. Duration was " |
| << duration.InSeconds() << " second(s)."; |
| UMA_HISTOGRAM_CUSTOM_TIMES( |
| "InstantTethering.HotspotUsageDuration", duration, |
| base::TimeDelta::FromSeconds(kMinDurationSeconds) /* min */, |
| base::TimeDelta::FromHours(kMaxDurationHours) /* max */, |
| kNumMetricsBuckets /* bucket_count */); |
| break; |
| } |
| default: |
| break; |
| } |
| } |
| |
| void HotspotUsageDurationTracker::HandleUnexpectedCurrentSession( |
| const ActiveHost::ActiveHostStatus& active_host_status) { |
| // If there is no start timestamp, no session is being tracked. |
| if (last_connection_start_.is_null()) |
| return; |
| |
| // It is expected that when a current session ends, the active host's status |
| // will change to DISCONNECTED. |
| if (active_host_status == ActiveHost::ActiveHostStatus::DISCONNECTED) |
| return; |
| |
| base::TimeDelta previous_duration = clock_->Now() - last_connection_start_; |
| PA_LOG(ERROR) << "Active host status changed to " |
| << ActiveHost::StatusToString(active_host_status) << ", but a " |
| << "session was already being tracked (" |
| << previous_duration.InSeconds() << " second(s)). " |
| << "Not recording any metrics for this session since this " |
| << "situation was reached in error."; |
| |
| // Delete the erroneously started session. |
| last_connection_start_ = base::Time(); |
| } |
| |
| } // namespace tether |
| |
| } // namespace chromeos |