blob: c218cf6cad6bf23adbdf3b72d7a118072ec4509c [file] [log] [blame]
// Copyright (c) 2013 The Chromium OS 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 SHILL_CELLULAR_CAPABILITY_UNIVERSAL_H_
#define SHILL_CELLULAR_CAPABILITY_UNIVERSAL_H_
#include <deque>
#include <map>
#include <string>
#include <vector>
#include <base/memory/scoped_ptr.h>
#include <base/memory/weak_ptr.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
#include <ModemManager/ModemManager.h>
#include "shill/accessor_interface.h"
#include "shill/cellular.h"
#include "shill/cellular_bearer.h"
#include "shill/cellular_capability.h"
#include "shill/mm1_modem_modem3gpp_proxy_interface.h"
#include "shill/mm1_modem_proxy_interface.h"
#include "shill/mm1_modem_simple_proxy_interface.h"
#include "shill/mm1_sim_proxy_interface.h"
#include "shill/out_of_credits_detector.h"
struct mobile_provider;
namespace shill {
class ModemInfo;
// CellularCapabilityUniversal handles modems using the
// org.chromium.ModemManager1 DBUS interface. This class is used for
// all types of modems, i.e. CDMA, GSM, and LTE modems.
class CellularCapabilityUniversal : public CellularCapability {
public:
typedef std::vector<DBusPropertiesMap> ScanResults;
typedef DBusPropertiesMap ScanResult;
typedef std::map<uint32_t, uint32_t> LockRetryData;
// Constants used in connect method call. Make available to test matchers.
// TODO(jglasgow): Generate from modem manager into
// ModemManager-names.h.
// See http://crbug.com/212909.
static const char kConnectPin[];
static const char kConnectOperatorId[];
static const char kConnectApn[];
static const char kConnectIPType[];
static const char kConnectUser[];
static const char kConnectPassword[];
static const char kConnectNumber[];
static const char kConnectAllowRoaming[];
static const char kConnectRMProtocol[];
CellularCapabilityUniversal(Cellular *cellular,
ProxyFactory *proxy_factory,
ModemInfo *modem_info);
~CellularCapabilityUniversal() override;
// Inherited from CellularCapability.
std::string GetTypeString() const override;
void OnDBusPropertiesChanged(
const std::string &interface,
const DBusPropertiesMap &changed_properties,
const std::vector<std::string> &invalidated_properties) override;
// Checks the modem state. If the state is kModemStateDisabled, then the
// modem is enabled. Otherwise, the enable command is buffered until the
// modem becomes disabled. ModemManager rejects the enable command if the
// modem is not disabled, for example, if it is initializing instead.
void StartModem(Error *error, const ResultCallback &callback) override;
void StopModem(Error *error, const ResultCallback &callback) override;
void Reset(Error *error, const ResultCallback &callback) override;
bool AreProxiesInitialized() const override;
bool IsServiceActivationRequired() const override;
void CompleteActivation(Error *error) override;
void Scan(Error *error, const ResultStringmapsCallback &callback) override;
void RegisterOnNetwork(const std::string &network_id,
Error *error,
const ResultCallback &callback) override;
bool IsRegistered() const override;
void SetUnregistered(bool searching) override;
void OnServiceCreated() override;
std::string GetNetworkTechnologyString() const override;
std::string GetRoamingStateString() const override;
bool AllowRoaming() override;
void GetSignalQuality() override;
void SetupConnectProperties(DBusPropertiesMap *properties) override;
void Connect(const DBusPropertiesMap &properties,
Error *error,
const ResultCallback &callback) override;
void Disconnect(Error *error, const ResultCallback &callback) override;
CellularBearer *GetActiveBearer() const override;
void RequirePIN(const std::string &pin,
bool require,
Error *error,
const ResultCallback &callback) override;
void EnterPIN(const std::string &pin,
Error *error,
const ResultCallback &callback) override;
void UnblockPIN(const std::string &unblock_code,
const std::string &pin,
Error *error,
const ResultCallback &callback) override;
void ChangePIN(const std::string &old_pin,
const std::string &new_pin,
Error *error,
const ResultCallback &callback) override;
virtual void GetProperties();
virtual void Register(const ResultCallback &callback);
protected:
virtual void InitProxies();
virtual void ReleaseProxies();
// Updates the |sim_path_| variable and creates a new proxy to the
// DBUS ModemManager1.Sim interface.
// TODO(armansito): Put this method in a 3GPP-only subclass.
virtual void OnSimPathChanged(const std::string &sim_path);
// Updates the online payment portal information, if any, for the cellular
// provider.
void UpdateServiceOLP() override;
// Post-payment activation handlers.
virtual void UpdatePendingActivationState();
// Returns the operator-specific form of |mdn|, which is passed to the online
// payment portal of a cellular operator.
std::string GetMdnForOLP(const MobileOperatorInfo *operator_info) const;
private:
struct ModemModes {
ModemModes()
: allowed_modes(MM_MODEM_MODE_NONE),
preferred_mode(MM_MODEM_MODE_NONE) {}
ModemModes(uint32_t allowed, MMModemMode preferred)
: allowed_modes(allowed),
preferred_mode(preferred) {}
uint32_t allowed_modes; // Bits based on MMModemMode.
MMModemMode preferred_mode; // A single MMModemMode bit.
};
// Constants used in scan results. Make available to unit tests.
// TODO(jglasgow): Generate from modem manager into ModemManager-names.h.
// See http://crbug.com/212909.
static const char kStatusProperty[];
static const char kOperatorLongProperty[];
static const char kOperatorShortProperty[];
static const char kOperatorCodeProperty[];
static const char kOperatorAccessTechnologyProperty[];
// Modem Model ID strings. From modem firmware via modemmanager.
static const char kE362ModelId[];
// Plugin strings via modemmanager.
static const char kAltairLTEMMPlugin[];
static const int64_t kActivationRegistrationTimeoutMilliseconds;
static const int64_t kEnterPinTimeoutMilliseconds;
static const int64_t kRegistrationDroppedUpdateTimeoutMilliseconds;
static const int kSetPowerStateTimeoutMilliseconds;
// Root path. The SIM path is reported by ModemManager to be the root path
// when no SIM is present.
static const char kRootPath[];
friend class CellularTest;
friend class CellularCapabilityTest;
friend class CellularCapabilityUniversalTest;
friend class CellularCapabilityUniversalCDMATest;
FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, PropertiesChanged);
FRIEND_TEST(CellularCapabilityUniversalMainTest, AllowRoaming);
FRIEND_TEST(CellularCapabilityUniversalMainTest,
ActivationWaitForRegisterTimeout);
FRIEND_TEST(CellularCapabilityUniversalMainTest, Connect);
FRIEND_TEST(CellularCapabilityUniversalMainTest, ConnectApns);
FRIEND_TEST(CellularCapabilityUniversalMainTest, DisconnectNoProxy);
FRIEND_TEST(CellularCapabilityUniversalMainTest,
DisconnectWithDeferredCallback);
FRIEND_TEST(CellularCapabilityUniversalMainTest, ExtractPcoValue);
FRIEND_TEST(CellularCapabilityUniversalMainTest, GetMdnForOLP);
FRIEND_TEST(CellularCapabilityUniversalMainTest,
GetNetworkTechnologyStringOnE362);
FRIEND_TEST(CellularCapabilityUniversalMainTest,
GetOutOfCreditsDetectionType);
FRIEND_TEST(CellularCapabilityUniversalMainTest, GetTypeString);
FRIEND_TEST(CellularCapabilityUniversalMainTest, IsMdnValid);
FRIEND_TEST(CellularCapabilityUniversalMainTest, IsRegistered);
FRIEND_TEST(CellularCapabilityUniversalMainTest, IsServiceActivationRequired);
FRIEND_TEST(CellularCapabilityUniversalMainTest, IsValidSimPath);
FRIEND_TEST(CellularCapabilityUniversalMainTest, NormalizeMdn);
FRIEND_TEST(CellularCapabilityUniversalMainTest, OnLockRetriesChanged);
FRIEND_TEST(CellularCapabilityUniversalMainTest, OnLockTypeChanged);
FRIEND_TEST(CellularCapabilityUniversalMainTest,
OnModemCurrentCapabilitiesChanged);
FRIEND_TEST(CellularCapabilityUniversalMainTest, OnSimLockPropertiesChanged);
FRIEND_TEST(CellularCapabilityUniversalMainTest, PropertiesChanged);
FRIEND_TEST(CellularCapabilityUniversalMainTest, Reset);
FRIEND_TEST(CellularCapabilityUniversalMainTest, Scan);
FRIEND_TEST(CellularCapabilityUniversalMainTest, ScanFailure);
FRIEND_TEST(CellularCapabilityUniversalMainTest, SimLockStatusChanged);
FRIEND_TEST(CellularCapabilityUniversalMainTest, SimLockStatusToProperty);
FRIEND_TEST(CellularCapabilityUniversalMainTest, SimPathChanged);
FRIEND_TEST(CellularCapabilityUniversalMainTest, SimPropertiesChanged);
FRIEND_TEST(CellularCapabilityUniversalMainTest, StartModem);
FRIEND_TEST(CellularCapabilityUniversalMainTest, StartModemFailure);
FRIEND_TEST(CellularCapabilityUniversalMainTest, StartModemInWrongState);
FRIEND_TEST(CellularCapabilityUniversalMainTest,
StartModemWithDeferredEnableFailure);
FRIEND_TEST(CellularCapabilityUniversalMainTest, StopModem);
FRIEND_TEST(CellularCapabilityUniversalMainTest, StopModemAltair);
FRIEND_TEST(CellularCapabilityUniversalMainTest,
StopModemAltairDeleteBearerFailure);
FRIEND_TEST(CellularCapabilityUniversalMainTest, StopModemAltairNotConnected);
FRIEND_TEST(CellularCapabilityUniversalMainTest, StopModemConnected);
FRIEND_TEST(CellularCapabilityUniversalMainTest, TerminationAction);
FRIEND_TEST(CellularCapabilityUniversalMainTest,
TerminationActionRemovedByStopModem);
FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateActiveBearer);
FRIEND_TEST(CellularCapabilityUniversalMainTest,
UpdatePendingActivationState);
FRIEND_TEST(CellularCapabilityUniversalMainTest,
UpdateRegistrationState);
FRIEND_TEST(CellularCapabilityUniversalMainTest,
UpdateRegistrationStateModemNotConnected);
FRIEND_TEST(CellularCapabilityUniversalMainTest,
UpdateServiceActivationState);
FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateServiceOLP);
FRIEND_TEST(CellularCapabilityUniversalTimerTest, CompleteActivation);
FRIEND_TEST(CellularTest, EnableTrafficMonitor);
FRIEND_TEST(CellularTest,
HandleNewRegistrationStateForServiceRequiringActivation);
FRIEND_TEST(CellularTest, ModemStateChangeLostRegistration);
FRIEND_TEST(CellularTest, OnPPPDied);
// SimLockStatus represents the fields in the Cellular.SIMLockStatus
// DBUS property of the shill device.
struct SimLockStatus {
public:
SimLockStatus() : enabled(false),
lock_type(MM_MODEM_LOCK_UNKNOWN),
retries_left(0) {}
bool enabled;
MMModemLock lock_type;
uint32_t retries_left;
};
// SubscriptionState represents the provisioned state of SIM. It is used
// currently by activation logic for LTE to determine if activation process is
// complete.
enum SubscriptionState {
kSubscriptionStateUnknown = 0,
kSubscriptionStateUnprovisioned = 1,
kSubscriptionStateProvisioned = 2,
kSubscriptionStateOutOfData = 3
};
// Methods used in starting a modem
void EnableModem(bool deferralbe,
Error *error,
const ResultCallback& callback);
void EnableModemCompleted(bool deferrable,
const ResultCallback &callback,
const Error &error);
// Methods used in stopping a modem
void Stop_DeleteActiveBearer(const ResultCallback &callback);
void Stop_DeleteActiveBearerCompleted(const ResultCallback &callback,
const Error &error);
void Stop_Disable(const ResultCallback &callback);
void Stop_DisableCompleted(const ResultCallback &callback,
const Error &error);
void Stop_PowerDown(const ResultCallback &callback);
void Stop_PowerDownCompleted(const ResultCallback &callback,
const Error &error);
// Updates |active_bearer_| to match the currently active bearer.
void UpdateActiveBearer();
Stringmap ParseScanResult(const ScanResult &result);
KeyValueStore SimLockStatusToProperty(Error *error);
void SetupApnTryList();
void FillConnectPropertyMap(DBusPropertiesMap *properties);
void HelpRegisterConstDerivedKeyValueStore(
const std::string &name,
KeyValueStore(CellularCapabilityUniversal::*get)(Error *error));
// Returns true if a connect error should be retried. This function
// abstracts modem specific behavior for modems which do a lousy job
// of returning specific errors on connect failures.
bool RetriableConnectError(const Error &error) const;
// Signal callbacks
void OnNetworkModeSignal(uint32_t mode);
void OnModemStateChangedSignal(int32_t old_state,
int32_t new_state,
uint32_t reason);
// Property Change notification handlers
void OnModemPropertiesChanged(
const DBusPropertiesMap &properties,
const std::vector<std::string> &invalidated_properties);
void OnSignalQualityChanged(uint32_t quality);
void OnSupportedCapabilitesChanged(
const std::vector<uint32_t> &supported_capabilities);
void OnModemCurrentCapabilitiesChanged(uint32_t current_capabilities);
void OnMdnChanged(const std::string &mdn);
void OnModemRevisionChanged(const std::string &revision);
void OnModemStateChanged(Cellular::ModemState state);
void OnAccessTechnologiesChanged(uint32_t access_technologies);
void OnSupportedModesChanged(const std::vector<ModemModes> &supported_modes);
void OnCurrentModesChanged(const ModemModes &current_modes);
void OnBearersChanged(const RpcIdentifiers &bearers);
void OnLockRetriesChanged(const LockRetryData &lock_retries);
void OnLockTypeChanged(MMModemLock unlock_required);
void OnSimLockStatusChanged();
// Returns false if the MDN is empty or if the MDN consists of all 0s.
bool IsMdnValid() const;
// 3GPP property change handlers
virtual void OnModem3GPPPropertiesChanged(
const DBusPropertiesMap &properties,
const std::vector<std::string> &invalidated_properties);
void On3GPPRegistrationChanged(MMModem3gppRegistrationState state,
const std::string &operator_code,
const std::string &operator_name);
void Handle3GPPRegistrationChange(
MMModem3gppRegistrationState updated_state,
std::string updated_operator_code,
std::string updated_operator_name);
void On3GPPSubscriptionStateChanged(MMModem3gppSubscriptionState state);
void OnFacilityLocksChanged(uint32_t locks);
// SIM property change handlers
// TODO(armansito): Put these methods in a 3GPP-only subclass.
void OnSimPropertiesChanged(
const DBusPropertiesMap &props,
const std::vector<std::string> &invalidated_properties);
void OnSpnChanged(const std::string &spn);
void OnSimIdentifierChanged(const std::string &id);
void OnOperatorIdChanged(const std::string &operator_id);
void OnOperatorNameChanged(const std::string &operator_name);
// Method callbacks
void OnRegisterReply(const ResultCallback &callback,
const Error &error);
void OnResetReply(const ResultCallback &callback, const Error &error);
void OnScanReply(const ResultStringmapsCallback &callback,
const ScanResults &results,
const Error &error);
void OnConnectReply(const ResultCallback &callback,
const DBus::Path &bearer,
const Error &error);
// Returns true, if |sim_path| constitutes a valid SIM path. Currently, a
// path is accepted to be valid, as long as it is not equal to one of ""
// and "/".
bool IsValidSimPath(const std::string &sim_path) const;
// Returns the normalized version of |mdn| by keeping only digits in |mdn|
// and removing other non-digit characters.
std::string NormalizeMdn(const std::string &mdn) const;
// Post-payment activation handlers.
void ResetAfterActivation();
void UpdateServiceActivationState();
void OnResetAfterActivationReply(const Error &error);
static bool IsRegisteredState(MMModem3gppRegistrationState state);
// Returns the out-of-credits detection algorithm to be used on this modem.
OutOfCreditsDetector::OOCType GetOutOfCreditsDetectionType() const;
// For unit tests.
void set_active_bearer(CellularBearer *bearer) {
active_bearer_.reset(bearer); // Takes ownership
}
scoped_ptr<mm1::ModemModem3gppProxyInterface> modem_3gpp_proxy_;
scoped_ptr<mm1::ModemProxyInterface> modem_proxy_;
scoped_ptr<mm1::ModemSimpleProxyInterface> modem_simple_proxy_;
scoped_ptr<mm1::SimProxyInterface> sim_proxy_;
// Used to enrich information about the network operator in |ParseScanResult|.
// TODO(pprabhu) Instead instantiate a local |MobileOperatorInfo| instance
// once the context has been separated out. (crbug.com/363874)
scoped_ptr<MobileOperatorInfo> mobile_operator_info_;
base::WeakPtrFactory<CellularCapabilityUniversal> weak_ptr_factory_;
MMModem3gppRegistrationState registration_state_;
// Bits based on MMModemCapabilities
std::vector<uint32_t> supported_capabilities_; // Technologies supported
uint32_t current_capabilities_; // Technologies supported without a reload
uint32_t access_technologies_; // Bits based on MMModemAccessTechnology
std::vector<ModemModes> supported_modes_;
ModemModes current_modes_;
Cellular::Operator serving_operator_;
std::string spn_;
std::string desired_network_;
// Properties.
std::deque<Stringmap> apn_try_list_;
bool resetting_;
SimLockStatus sim_lock_status_;
SubscriptionState subscription_state_;
std::string sim_path_;
scoped_ptr<CellularBearer> active_bearer_;
RpcIdentifiers bearer_paths_;
bool reset_done_;
// If the modem is not in a state to be enabled when StartModem is called,
// enabling is deferred using this callback.
base::Closure deferred_enable_modem_callback_;
// Sometimes flaky cellular network causes the 3GPP registration state to
// rapidly change from registered --> searching and back. Delay such updates
// a little to smooth over temporary registration loss.
base::CancelableClosure registration_dropped_update_callback_;
int64_t registration_dropped_update_timeout_milliseconds_;
DISALLOW_COPY_AND_ASSIGN(CellularCapabilityUniversal);
};
} // namespace shill
#endif // SHILL_CELLULAR_CAPABILITY_UNIVERSAL_H_