[go: nahoru, domu]

blob: b96c33a8dacf4f8c6ad65a3155f1d124430aef3e [file] [log] [blame]
// Copyright (c) 2019 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.
#ifndef CHROMEOS_NETWORK_CELLULAR_METRICS_LOGGER_H_
#define CHROMEOS_NETWORK_CELLULAR_METRICS_LOGGER_H_
#include "base/component_export.h"
#include "base/containers/flat_map.h"
#include "base/gtest_prod_util.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/timer/timer.h"
#include "chromeos/login/login_state/login_state.h"
#include "chromeos/network/network_connection_observer.h"
#include "chromeos/network/network_state_handler_observer.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace chromeos {
class CellularESimProfileHandler;
class CellularMetricsLoggerTest;
class ESimFeatureUsageMetrics;
class NetworkConnectionHandler;
class NetworkState;
class NetworkStateHandler;
// Cellular network SIM types.
enum class SimType {
kPSim,
kESim,
};
// Class for tracking cellular network related metrics.
//
// This class adds observers on network state and makes the following
// measurements on cellular networks:
// 1. Time to connected.
// 2. Connected states and non-user initiated disconnections.
// 3. Activation status at login.
// 4. Cellular network usage type.
//
// Note: This class does not start logging metrics until Init() is
// invoked.
class COMPONENT_EXPORT(CHROMEOS_NETWORK) CellularMetricsLogger
: public NetworkStateHandlerObserver,
public LoginState::Observer,
public NetworkConnectionObserver {
public:
// Histograms associated with SIM Pin operations.
static const char kSimPinLockSuccessHistogram[];
static const char kSimPinUnlockSuccessHistogram[];
static const char kSimPinUnblockSuccessHistogram[];
static const char kSimPinChangeSuccessHistogram[];
// Histograms associated with user initiated connection success.
static const char kESimUserInitiatedConnectionResultHistogram[];
static const char kPSimUserInitiatedConnectionResultHistogram[];
// Histograms associated with all connection success.
static const char kESimAllConnectionResultHistogram[];
static const char kESimPolicyAllConnectionResultHistogram[];
static const char kPSimAllConnectionResultHistogram[];
// PIN operations that are tracked by metrics.
enum class SimPinOperation {
kLock = 0,
kUnlock = 1,
kUnblock = 2,
kChange = 3,
};
// Records the result of pin operations performed.
static void RecordSimPinOperationResult(
const SimPinOperation& pin_operation,
const absl::optional<std::string>& shill_error_name = absl::nullopt);
CellularMetricsLogger();
CellularMetricsLogger(const CellularMetricsLogger&) = delete;
CellularMetricsLogger& operator=(const CellularMetricsLogger&) = delete;
~CellularMetricsLogger() override;
void Init(NetworkStateHandler* network_state_handler,
NetworkConnectionHandler* network_connection_handler,
CellularESimProfileHandler* cellular_esim_profile_handler);
// LoginState::Observer:
void LoggedInStateChanged() override;
// NetworkStateHandlerObserver::
void DeviceListChanged() override;
void NetworkListChanged() override;
void NetworkConnectionStateChanged(const NetworkState* network) override;
void OnShuttingDown() override;
// NetworkConnectionObserver::
void ConnectSucceeded(const std::string& service_path) override;
void ConnectFailed(const std::string& service_path,
const std::string& error_name) override;
void DisconnectRequested(const std::string& service_path) override;
private:
friend class CellularMetricsLoggerTest;
FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest,
DuplicateCellularServiceGuids);
FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest, CellularConnectResult);
FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest,
CancellationDuringConnecting);
FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest,
UserInitiatedConnectionResult);
FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest,
CellularESimProfileStatusAtLoginTest);
FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest,
CellularServiceAtLoginTest);
FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest, CellularUsageCountTest);
FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest,
CellularUsageCountDongleTest);
FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest,
CellularPSimActivationStateAtLoginTest);
FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest,
CellularTimeToConnectedTest);
FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest,
CellularDisconnectionsTest);
FRIEND_TEST_ALL_PREFIXES(NetworkDeviceHandlerTest, RequirePin);
FRIEND_TEST_ALL_PREFIXES(NetworkDeviceHandlerTest, EnterPin);
FRIEND_TEST_ALL_PREFIXES(NetworkDeviceHandlerTest, UnblockPin);
FRIEND_TEST_ALL_PREFIXES(NetworkDeviceHandlerTest, ChangePin);
// The amount of time after cellular device is added to device list,
// after which cellular device is considered initialized.
static const base::TimeDelta kInitializationTimeout;
// The amount of time after a disconnect request within which any
// disconnections are considered user initiated.
static const base::TimeDelta kDisconnectRequestTimeout;
// Stores connection related information for a cellular network.
struct ConnectionInfo {
explicit ConnectionInfo(const std::string& network_guid);
ConnectionInfo(const std::string& network_guid,
bool is_connected,
bool is_connecting);
~ConnectionInfo();
const std::string network_guid;
absl::optional<bool> is_connected;
bool is_connecting = false;
// Tracks whether a disconnect was requested from chrome on a network that
// was previously in the connecting state. This field is set back to false
// when shill connection failures are checked in
// NetworkConnectionStateChanged().
bool disconnect_requested = false;
absl::optional<base::TimeTicks> last_disconnect_request_time;
absl::optional<base::TimeTicks> last_connect_start_time;
};
// Usage type for cellular network. These values are persisted to logs.
// Entries should not be renumbered and numeric values should never
// be reused.
enum class CellularUsage {
kConnectedAndOnlyNetwork = 0,
kConnectedWithOtherNetwork = 1,
kNotConnected = 2,
kMaxValue = kNotConnected
};
// Activation state for PSim cellular network.
// These values are persisted to logs. Entries should not be renumbered
// and numeric values should never be reused.
enum class PSimActivationState {
kActivated = 0,
kActivating = 1,
kNotActivated = 2,
kPartiallyActivated = 3,
kUnknown = 4,
kMaxValue = kUnknown
};
// Profile status for ESim cellular network.
// These values are persisted to logs. Entries should not be renumbered
// and numeric values should never be reused.
enum class ESimProfileStatus {
kActive = 0,
kActiveWithPendingProfiles = 1,
kPendingProfilesOnly = 2,
kNoProfiles = 3,
kMaxValue = kNoProfiles
};
// Cellular connection state. These values are persisted to logs.
// Entries should not be renumbered and numeric values should
// never be reused.
enum class ConnectionState {
kConnected = 0,
kDisconnected = 1,
kMaxValue = kDisconnected
};
// Result of PIN operations.
// These values are persisted to logs. Entries should not be renumbered
// and numeric values should never be reused.
// Note: With the exception of Success, enums should match the
// error names listed near the top of NetworkDeviceHandler.
enum class SimPinOperationResult {
kSuccess = 0,
kErrorDeviceMissing = 1,
kErrorFailure = 2,
kErrorIncorrectPin = 3,
kErrorNotFound = 4,
kErrorNotSupported = 5,
kErrorPinBlocked = 6,
kErrorPinRequired = 7,
kErrorTimeout = 8,
kErrorUnknown = 9,
kMaxValue = kErrorUnknown,
};
// This enum is used to track the connection results from
// NetworkConnectionHandler. With the exception of kSuccess and kUnknown,
// these enums are mapped to relevant NetworkConnectionHandler errors
// associated to user initiated connection errors.
// These values are persisted to logs. Entries should not be renumbered
// and numeric values should never be reused.
enum class ConnectResult {
kSuccess = 0,
kUnknown = 1,
kInvalidGuid = 2,
kInvalidState = 3,
kCanceled = 4,
kNotConfigured = 5,
kBlocked = 6,
kCellularInhibitFailure = 7,
kESimProfileIssue = 8,
kCellularOutOfCredits = 9,
kSimLocked = 10,
kConnectFailed = 11,
kNotConnected = 12,
kActivateFailed = 13,
kEnabledOrDisabledWhenNotAvailable = 14,
kErrorCellularDeviceBusy = 15,
kErrorConnectTimeout = 16,
kConnectableCellularTimeout = 17,
kMaxValue = kConnectableCellularTimeout,
};
// Result of state changes to a cellular network triggered by any connection
// attempt. With the exception of kSuccess and kUnknown, these enums are
// mapped directly to Shill errors. These values are persisted to logs.
// Entries should not be renumbered and numeric values should never be reused.
enum class ShillConnectResult {
kSuccess = 0,
kUnknown = 1,
kFailedToConnect = 2,
kDhcpFailure = 3,
kDnsLookupFailure = 4,
kEapAuthentication = 5,
kEapLocalTls = 6,
kEapRemoteTls = 7,
kOutOfRange = 8,
kPinMissing = 9,
kNoFailure = 10,
kNotAssociated = 11,
kNotAuthenticated = 12,
kTooManySTAs = 13,
kBadPassphrase = 14,
kBadWepKey = 15,
kErrorSimLocked = 16,
kErrorNotRegistered = 17,
kMaxValue = kErrorNotRegistered,
};
// Convert shill error name string to SimPinOperationResult enum.
static SimPinOperationResult GetSimPinOperationResultForShillError(
const std::string& shill_error_name);
// Converts a NetworkConnectionHandler string error to a ConnectResult enum.
static ConnectResult NetworkConnectionErrorToConnectResult(
const std::string& error_name);
// Converts a Shill error string to a ShillConnectResult enum.
static ShillConnectResult ShillErrorToConnectResult(
const std::string& error_name);
static void LogCellularUserInitiatedConnectionSuccessHistogram(
ConnectResult start_connect_result,
SimType sim_type);
// Returns null if there is no network with the given path or if the
// network is non-cellular.
const NetworkState* GetCellularNetwork(const std::string& service_path);
// Convert shill activation state string to PSimActivationState enum
PSimActivationState PSimActivationStateToEnum(const std::string& state);
// Helper method to save cellular disconnections histogram.
void LogCellularDisconnectionsHistogram(ConnectionState connection_state,
SimType sim_type,
bool is_managed_by_policy);
void LogCellularAllConnectionSuccessHistogram(
ShillConnectResult start_connect_result,
SimType sim_type,
bool is_managed_by_policy);
void OnInitializationTimeout();
// Tracks cellular network connection state and logs time to connected.
void CheckForTimeToConnectedMetric(const NetworkState* network);
// Tracks cellular network connected states and non user initiated
// disconnections.
void CheckForConnectionStateMetric(const NetworkState* network);
// Tracks the activation state of the PSim cellular network if available and
// if |is_psim_activation_state_logged_| is false.
void CheckForPSimActivationStateMetric();
// Tracks the activation state of ESim cellular networks if available and
// if |is_esim_profile_status_logged_| is false.
void CheckForESimProfileStatusMetric();
// Tracks failed connection attempts.
void CheckForShillConnectionFailureMetric(const NetworkState* network);
// This checks the state of connected networks and logs
// cellular network usage histogram. Histogram is only logged
// when usage state changes.
void CheckForCellularUsageMetrics();
// Tracks how many eSIM profiles are installed on the device and how many pSIM
// networks are available on the device if |is_service_count_logged_| is true.
void CheckForCellularServiceCountMetric();
// Handles ESim Standard Feature Usage Logging metrics when the cellular usage
// changes for an ESim network.
void HandleESimFeatureUsageChange(CellularUsage last_esim_cellular_usage,
CellularUsage current_usage);
// Returns the ConnectionInfo for given |cellular_network_guid|.
ConnectionInfo* GetConnectionInfoForCellularNetwork(
const std::string& cellular_network_guid);
// Tracks the last cellular network usage state.
absl::optional<CellularUsage> last_cellular_usage_;
// Tracks the last PSim cellular network usage state.
absl::optional<CellularUsage> last_psim_cellular_usage_;
// Tracks the last time the PSim network's cellular usage changed.
absl::optional<base::ElapsedTimer> psim_usage_elapsed_timer_;
// Tracks the last ESim cellular network usage state.
absl::optional<CellularUsage> last_esim_cellular_usage_;
// Tracks the last time ESim network's cellular usage is managed or not.
bool last_managed_by_policy_ = false;
// Tracks the last time the ESim network's cellular usage changed.
absl::optional<base::ElapsedTimer> esim_usage_elapsed_timer_;
// Tracks whether cellular device is available or not.
bool is_cellular_available_ = false;
NetworkStateHandler* network_state_handler_ = nullptr;
NetworkConnectionHandler* network_connection_handler_ = nullptr;
CellularESimProfileHandler* cellular_esim_profile_handler_ = nullptr;
// A timer to wait for cellular initialization. This is useful
// to avoid tracking intermediate states when cellular network is
// starting up.
base::OneShotTimer initialization_timer_;
// Tracks whether the PSim activation state is already logged for this
// session.
bool is_psim_activation_state_logged_ = false;
// Tracks whether the ESim profile status is already logged for this
// session.
bool is_esim_profile_status_logged_ = false;
// Tracks whether service count is already logged for this session.
bool is_service_count_logged_ = false;
// Stores connection information for all cellular networks.
base::flat_map<std::string, std::unique_ptr<ConnectionInfo>>
guid_to_connection_info_map_;
bool initialized_ = false;
// Tracks ESim feature usage for the Standard Feature Usage Logging Framework.
std::unique_ptr<ESimFeatureUsageMetrics> esim_feature_usage_metrics_;
};
} // namespace chromeos
#endif // CHROMEOS_NETWORK_CELLULAR_METRICS_LOGGER_H_