454 lines
19 KiB
C++
454 lines
19 KiB
C++
//
|
|
// Copyright (C) 2013 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#ifndef SHILL_CELLULAR_CELLULAR_CAPABILITY_UNIVERSAL_H_
|
|
#define SHILL_CELLULAR_CELLULAR_CAPABILITY_UNIVERSAL_H_
|
|
|
|
#include <deque>
|
|
#include <map>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <vector>
|
|
|
|
#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/cellular.h"
|
|
#include "shill/cellular/cellular_bearer.h"
|
|
#include "shill/cellular/cellular_capability.h"
|
|
#include "shill/cellular/mm1_modem_modem3gpp_proxy_interface.h"
|
|
#include "shill/cellular/mm1_modem_proxy_interface.h"
|
|
#include "shill/cellular/mm1_modem_simple_proxy_interface.h"
|
|
#include "shill/cellular/mm1_sim_proxy_interface.h"
|
|
#include "shill/cellular/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<KeyValueStore> ScanResults;
|
|
typedef KeyValueStore ScanResult;
|
|
typedef std::map<uint32_t, uint32_t> LockRetryData;
|
|
typedef std::tuple<uint32_t, bool> SignalQuality;
|
|
typedef std::tuple<uint32_t, uint32_t> ModesData;
|
|
typedef std::vector<ModesData> SupportedModes;
|
|
|
|
// 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,
|
|
ControlInterface* control_interface,
|
|
ModemInfo* modem_info);
|
|
~CellularCapabilityUniversal() override;
|
|
|
|
// Inherited from CellularCapability.
|
|
std::string GetTypeString() const override;
|
|
void OnPropertiesChanged(
|
|
const std::string& interface,
|
|
const KeyValueStore& 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(KeyValueStore* properties) override;
|
|
void Connect(const KeyValueStore& 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();
|
|
void ReleaseProxies() override;
|
|
|
|
// 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[];
|
|
|
|
// Plugin strings via ModemManager.
|
|
static const char kAltairLTEMMPlugin[];
|
|
static const char kNovatelLTEMMPlugin[];
|
|
|
|
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(KeyValueStore* 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 KeyValueStore& 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 KeyValueStore& 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 KeyValueStore& 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 std::string& 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
|
|
}
|
|
|
|
std::unique_ptr<mm1::ModemModem3gppProxyInterface> modem_3gpp_proxy_;
|
|
std::unique_ptr<mm1::ModemProxyInterface> modem_proxy_;
|
|
std::unique_ptr<mm1::ModemSimpleProxyInterface> modem_simple_proxy_;
|
|
std::unique_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)
|
|
std::unique_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_;
|
|
|
|
Stringmap 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_;
|
|
std::unique_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_CELLULAR_CAPABILITY_UNIVERSAL_H_
|