1//
2// Copyright (C) 2013 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#ifndef SHILL_CELLULAR_CELLULAR_CAPABILITY_UNIVERSAL_H_
18#define SHILL_CELLULAR_CELLULAR_CAPABILITY_UNIVERSAL_H_
19
20#include <deque>
21#include <map>
22#include <string>
23#include <tuple>
24#include <vector>
25
26#include <base/memory/weak_ptr.h>
27#include <gtest/gtest_prod.h>  // for FRIEND_TEST
28#include <ModemManager/ModemManager.h>
29
30#include "shill/accessor_interface.h"
31#include "shill/cellular/cellular.h"
32#include "shill/cellular/cellular_bearer.h"
33#include "shill/cellular/cellular_capability.h"
34#include "shill/cellular/mm1_modem_modem3gpp_proxy_interface.h"
35#include "shill/cellular/mm1_modem_proxy_interface.h"
36#include "shill/cellular/mm1_modem_simple_proxy_interface.h"
37#include "shill/cellular/mm1_sim_proxy_interface.h"
38#include "shill/cellular/out_of_credits_detector.h"
39
40struct mobile_provider;
41
42namespace shill {
43
44class ModemInfo;
45
46// CellularCapabilityUniversal handles modems using the
47// org.chromium.ModemManager1 DBUS interface.  This class is used for
48// all types of modems, i.e. CDMA, GSM, and LTE modems.
49class CellularCapabilityUniversal : public CellularCapability {
50 public:
51  typedef std::vector<KeyValueStore> ScanResults;
52  typedef KeyValueStore ScanResult;
53  typedef std::map<uint32_t, uint32_t> LockRetryData;
54  typedef std::tuple<uint32_t, bool> SignalQuality;
55  typedef std::tuple<uint32_t, uint32_t> ModesData;
56  typedef std::vector<ModesData> SupportedModes;
57
58  // Constants used in connect method call.  Make available to test matchers.
59  // TODO(jglasgow): Generate from modem manager into
60  // ModemManager-names.h.
61  // See http://crbug.com/212909.
62  static const char kConnectPin[];
63  static const char kConnectOperatorId[];
64  static const char kConnectApn[];
65  static const char kConnectIPType[];
66  static const char kConnectUser[];
67  static const char kConnectPassword[];
68  static const char kConnectNumber[];
69  static const char kConnectAllowRoaming[];
70  static const char kConnectRMProtocol[];
71
72  CellularCapabilityUniversal(Cellular* cellular,
73                              ControlInterface* control_interface,
74                              ModemInfo* modem_info);
75  ~CellularCapabilityUniversal() override;
76
77  // Inherited from CellularCapability.
78  std::string GetTypeString() const override;
79  void OnPropertiesChanged(
80      const std::string& interface,
81      const KeyValueStore& changed_properties,
82      const std::vector<std::string>& invalidated_properties) override;
83  // Checks the modem state.  If the state is kModemStateDisabled, then the
84  // modem is enabled.  Otherwise, the enable command is buffered until the
85  // modem becomes disabled.  ModemManager rejects the enable command if the
86  // modem is not disabled, for example, if it is initializing instead.
87  void StartModem(Error* error, const ResultCallback& callback) override;
88  void StopModem(Error* error, const ResultCallback& callback) override;
89  void Reset(Error* error, const ResultCallback& callback) override;
90  bool AreProxiesInitialized() const override;
91  bool IsServiceActivationRequired() const override;
92  void CompleteActivation(Error* error) override;
93  void Scan(Error* error, const ResultStringmapsCallback& callback) override;
94  void RegisterOnNetwork(const std::string& network_id,
95                         Error* error,
96                         const ResultCallback& callback) override;
97  bool IsRegistered() const override;
98  void SetUnregistered(bool searching) override;
99  void OnServiceCreated() override;
100  std::string GetNetworkTechnologyString() const override;
101  std::string GetRoamingStateString() const override;
102  bool AllowRoaming() override;
103  void GetSignalQuality() override;
104  void SetupConnectProperties(KeyValueStore* properties) override;
105  void Connect(const KeyValueStore& properties,
106               Error* error,
107               const ResultCallback& callback) override;
108  void Disconnect(Error* error, const ResultCallback& callback) override;
109  CellularBearer* GetActiveBearer() const override;
110  void RequirePIN(const std::string& pin,
111                  bool require,
112                  Error* error,
113                  const ResultCallback& callback) override;
114  void EnterPIN(const std::string& pin,
115                Error* error,
116                const ResultCallback& callback) override;
117  void UnblockPIN(const std::string& unblock_code,
118                  const std::string& pin,
119                  Error* error,
120                  const ResultCallback& callback) override;
121  void ChangePIN(const std::string& old_pin,
122                 const std::string& new_pin,
123                 Error* error,
124                 const ResultCallback& callback) override;
125
126  virtual void GetProperties();
127  virtual void Register(const ResultCallback& callback);
128
129 protected:
130  virtual void InitProxies();
131  void ReleaseProxies() override;
132
133  // Updates the |sim_path_| variable and creates a new proxy to the
134  // DBUS ModemManager1.Sim interface.
135  // TODO(armansito): Put this method in a 3GPP-only subclass.
136  virtual void OnSimPathChanged(const std::string& sim_path);
137
138  // Updates the online payment portal information, if any, for the cellular
139  // provider.
140  void UpdateServiceOLP() override;
141
142  // Post-payment activation handlers.
143  virtual void UpdatePendingActivationState();
144
145  // Returns the operator-specific form of |mdn|, which is passed to the online
146  // payment portal of a cellular operator.
147  std::string GetMdnForOLP(const MobileOperatorInfo* operator_info) const;
148
149 private:
150  struct ModemModes {
151    ModemModes()
152        : allowed_modes(MM_MODEM_MODE_NONE),
153          preferred_mode(MM_MODEM_MODE_NONE) {}
154
155    ModemModes(uint32_t allowed, MMModemMode preferred)
156        : allowed_modes(allowed),
157          preferred_mode(preferred) {}
158
159    uint32_t allowed_modes;        // Bits based on MMModemMode.
160    MMModemMode preferred_mode;  // A single MMModemMode bit.
161  };
162
163  // Constants used in scan results.  Make available to unit tests.
164  // TODO(jglasgow): Generate from modem manager into ModemManager-names.h.
165  // See http://crbug.com/212909.
166  static const char kStatusProperty[];
167  static const char kOperatorLongProperty[];
168  static const char kOperatorShortProperty[];
169  static const char kOperatorCodeProperty[];
170  static const char kOperatorAccessTechnologyProperty[];
171
172  // Plugin strings via ModemManager.
173  static const char kAltairLTEMMPlugin[];
174  static const char kNovatelLTEMMPlugin[];
175
176  static const int64_t kActivationRegistrationTimeoutMilliseconds;
177  static const int64_t kEnterPinTimeoutMilliseconds;
178  static const int64_t kRegistrationDroppedUpdateTimeoutMilliseconds;
179  static const int kSetPowerStateTimeoutMilliseconds;
180
181
182  // Root path. The SIM path is reported by ModemManager to be the root path
183  // when no SIM is present.
184  static const char kRootPath[];
185
186  friend class CellularTest;
187  friend class CellularCapabilityTest;
188  friend class CellularCapabilityUniversalTest;
189  friend class CellularCapabilityUniversalCDMATest;
190  FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, PropertiesChanged);
191  FRIEND_TEST(CellularCapabilityUniversalMainTest, AllowRoaming);
192  FRIEND_TEST(CellularCapabilityUniversalMainTest,
193              ActivationWaitForRegisterTimeout);
194  FRIEND_TEST(CellularCapabilityUniversalMainTest, Connect);
195  FRIEND_TEST(CellularCapabilityUniversalMainTest, ConnectApns);
196  FRIEND_TEST(CellularCapabilityUniversalMainTest, DisconnectNoProxy);
197  FRIEND_TEST(CellularCapabilityUniversalMainTest,
198              DisconnectWithDeferredCallback);
199  FRIEND_TEST(CellularCapabilityUniversalMainTest, ExtractPcoValue);
200  FRIEND_TEST(CellularCapabilityUniversalMainTest, GetMdnForOLP);
201  FRIEND_TEST(CellularCapabilityUniversalMainTest,
202              GetNetworkTechnologyStringOnE362);
203  FRIEND_TEST(CellularCapabilityUniversalMainTest,
204              GetOutOfCreditsDetectionType);
205  FRIEND_TEST(CellularCapabilityUniversalMainTest, GetTypeString);
206  FRIEND_TEST(CellularCapabilityUniversalMainTest, IsMdnValid);
207  FRIEND_TEST(CellularCapabilityUniversalMainTest, IsRegistered);
208  FRIEND_TEST(CellularCapabilityUniversalMainTest, IsServiceActivationRequired);
209  FRIEND_TEST(CellularCapabilityUniversalMainTest, IsValidSimPath);
210  FRIEND_TEST(CellularCapabilityUniversalMainTest, NormalizeMdn);
211  FRIEND_TEST(CellularCapabilityUniversalMainTest, OnLockRetriesChanged);
212  FRIEND_TEST(CellularCapabilityUniversalMainTest, OnLockTypeChanged);
213  FRIEND_TEST(CellularCapabilityUniversalMainTest,
214              OnModemCurrentCapabilitiesChanged);
215  FRIEND_TEST(CellularCapabilityUniversalMainTest, OnSimLockPropertiesChanged);
216  FRIEND_TEST(CellularCapabilityUniversalMainTest, PropertiesChanged);
217  FRIEND_TEST(CellularCapabilityUniversalMainTest, Reset);
218  FRIEND_TEST(CellularCapabilityUniversalMainTest, Scan);
219  FRIEND_TEST(CellularCapabilityUniversalMainTest, ScanFailure);
220  FRIEND_TEST(CellularCapabilityUniversalMainTest, SimLockStatusChanged);
221  FRIEND_TEST(CellularCapabilityUniversalMainTest, SimLockStatusToProperty);
222  FRIEND_TEST(CellularCapabilityUniversalMainTest, SimPathChanged);
223  FRIEND_TEST(CellularCapabilityUniversalMainTest, SimPropertiesChanged);
224  FRIEND_TEST(CellularCapabilityUniversalMainTest, StartModem);
225  FRIEND_TEST(CellularCapabilityUniversalMainTest, StartModemFailure);
226  FRIEND_TEST(CellularCapabilityUniversalMainTest, StartModemInWrongState);
227  FRIEND_TEST(CellularCapabilityUniversalMainTest,
228              StartModemWithDeferredEnableFailure);
229  FRIEND_TEST(CellularCapabilityUniversalMainTest, StopModem);
230  FRIEND_TEST(CellularCapabilityUniversalMainTest, StopModemAltair);
231  FRIEND_TEST(CellularCapabilityUniversalMainTest,
232              StopModemAltairDeleteBearerFailure);
233  FRIEND_TEST(CellularCapabilityUniversalMainTest, StopModemAltairNotConnected);
234  FRIEND_TEST(CellularCapabilityUniversalMainTest, StopModemConnected);
235  FRIEND_TEST(CellularCapabilityUniversalMainTest, TerminationAction);
236  FRIEND_TEST(CellularCapabilityUniversalMainTest,
237              TerminationActionRemovedByStopModem);
238  FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateActiveBearer);
239  FRIEND_TEST(CellularCapabilityUniversalMainTest,
240              UpdatePendingActivationState);
241  FRIEND_TEST(CellularCapabilityUniversalMainTest,
242              UpdateRegistrationState);
243  FRIEND_TEST(CellularCapabilityUniversalMainTest,
244              UpdateRegistrationStateModemNotConnected);
245  FRIEND_TEST(CellularCapabilityUniversalMainTest,
246              UpdateServiceActivationState);
247  FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateServiceOLP);
248  FRIEND_TEST(CellularCapabilityUniversalTimerTest, CompleteActivation);
249  FRIEND_TEST(CellularTest, EnableTrafficMonitor);
250  FRIEND_TEST(CellularTest,
251              HandleNewRegistrationStateForServiceRequiringActivation);
252  FRIEND_TEST(CellularTest, ModemStateChangeLostRegistration);
253  FRIEND_TEST(CellularTest, OnPPPDied);
254
255  // SimLockStatus represents the fields in the Cellular.SIMLockStatus
256  // DBUS property of the shill device.
257  struct SimLockStatus {
258   public:
259    SimLockStatus() : enabled(false),
260                      lock_type(MM_MODEM_LOCK_UNKNOWN),
261                      retries_left(0) {}
262
263    bool enabled;
264    MMModemLock lock_type;
265    uint32_t retries_left;
266  };
267
268  // SubscriptionState represents the provisioned state of SIM. It is used
269  // currently by activation logic for LTE to determine if activation process is
270  // complete.
271  enum SubscriptionState {
272    kSubscriptionStateUnknown = 0,
273    kSubscriptionStateUnprovisioned = 1,
274    kSubscriptionStateProvisioned = 2,
275    kSubscriptionStateOutOfData = 3
276  };
277
278  // Methods used in starting a modem
279  void EnableModem(bool deferralbe,
280                   Error* error,
281                   const ResultCallback& callback);
282  void EnableModemCompleted(bool deferrable,
283                            const ResultCallback& callback,
284                            const Error& error);
285
286  // Methods used in stopping a modem
287  void Stop_DeleteActiveBearer(const ResultCallback& callback);
288  void Stop_DeleteActiveBearerCompleted(const ResultCallback& callback,
289                                        const Error& error);
290  void Stop_Disable(const ResultCallback& callback);
291  void Stop_DisableCompleted(const ResultCallback& callback,
292                             const Error& error);
293  void Stop_PowerDown(const ResultCallback& callback);
294  void Stop_PowerDownCompleted(const ResultCallback& callback,
295                               const Error& error);
296
297  // Updates |active_bearer_| to match the currently active bearer.
298  void UpdateActiveBearer();
299
300  Stringmap ParseScanResult(const ScanResult& result);
301
302  KeyValueStore SimLockStatusToProperty(Error* error);
303
304  void SetupApnTryList();
305  void FillConnectPropertyMap(KeyValueStore* properties);
306
307  void HelpRegisterConstDerivedKeyValueStore(
308      const std::string& name,
309      KeyValueStore(CellularCapabilityUniversal::*get)(Error* error));
310
311  // Returns true if a connect error should be retried.  This function
312  // abstracts modem specific behavior for modems which do a lousy job
313  // of returning specific errors on connect failures.
314  bool RetriableConnectError(const Error& error) const;
315
316  // Signal callbacks
317  void OnNetworkModeSignal(uint32_t mode);
318  void OnModemStateChangedSignal(int32_t old_state,
319                                 int32_t new_state,
320                                 uint32_t reason);
321
322  // Property Change notification handlers
323  void OnModemPropertiesChanged(
324      const KeyValueStore& properties,
325      const std::vector<std::string>& invalidated_properties);
326
327  void OnSignalQualityChanged(uint32_t quality);
328
329  void OnSupportedCapabilitesChanged(
330      const std::vector<uint32_t>& supported_capabilities);
331  void OnModemCurrentCapabilitiesChanged(uint32_t current_capabilities);
332  void OnMdnChanged(const std::string& mdn);
333  void OnModemRevisionChanged(const std::string& revision);
334  void OnModemStateChanged(Cellular::ModemState state);
335  void OnAccessTechnologiesChanged(uint32_t access_technologies);
336  void OnSupportedModesChanged(const std::vector<ModemModes>& supported_modes);
337  void OnCurrentModesChanged(const ModemModes& current_modes);
338  void OnBearersChanged(const RpcIdentifiers& bearers);
339  void OnLockRetriesChanged(const LockRetryData& lock_retries);
340  void OnLockTypeChanged(MMModemLock unlock_required);
341  void OnSimLockStatusChanged();
342
343  // Returns false if the MDN is empty or if the MDN consists of all 0s.
344  bool IsMdnValid() const;
345
346  // 3GPP property change handlers
347  virtual void OnModem3GPPPropertiesChanged(
348      const KeyValueStore& properties,
349      const std::vector<std::string>& invalidated_properties);
350  void On3GPPRegistrationChanged(MMModem3gppRegistrationState state,
351                                 const std::string& operator_code,
352                                 const std::string& operator_name);
353  void Handle3GPPRegistrationChange(
354      MMModem3gppRegistrationState updated_state,
355      std::string updated_operator_code,
356      std::string updated_operator_name);
357  void On3GPPSubscriptionStateChanged(MMModem3gppSubscriptionState state);
358  void OnFacilityLocksChanged(uint32_t locks);
359
360  // SIM property change handlers
361  // TODO(armansito): Put these methods in a 3GPP-only subclass.
362  void OnSimPropertiesChanged(
363      const KeyValueStore& props,
364      const std::vector<std::string>& invalidated_properties);
365  void OnSpnChanged(const std::string& spn);
366  void OnSimIdentifierChanged(const std::string& id);
367  void OnOperatorIdChanged(const std::string& operator_id);
368  void OnOperatorNameChanged(const std::string& operator_name);
369
370  // Method callbacks
371  void OnRegisterReply(const ResultCallback& callback,
372                       const Error& error);
373  void OnResetReply(const ResultCallback& callback, const Error& error);
374  void OnScanReply(const ResultStringmapsCallback& callback,
375                   const ScanResults& results,
376                   const Error& error);
377  void OnConnectReply(const ResultCallback& callback,
378                      const std::string& bearer,
379                      const Error& error);
380
381  // Returns true, if |sim_path| constitutes a valid SIM path. Currently, a
382  // path is accepted to be valid, as long as it is not equal to one of ""
383  // and "/".
384  bool IsValidSimPath(const std::string& sim_path) const;
385
386  // Returns the normalized version of |mdn| by keeping only digits in |mdn|
387  // and removing other non-digit characters.
388  std::string NormalizeMdn(const std::string& mdn) const;
389
390  // Post-payment activation handlers.
391  void ResetAfterActivation();
392  void UpdateServiceActivationState();
393  void OnResetAfterActivationReply(const Error& error);
394
395  static bool IsRegisteredState(MMModem3gppRegistrationState state);
396
397  // Returns the out-of-credits detection algorithm to be used on this modem.
398  OutOfCreditsDetector::OOCType GetOutOfCreditsDetectionType() const;
399
400  // For unit tests.
401  void set_active_bearer(CellularBearer* bearer) {
402    active_bearer_.reset(bearer);  // Takes ownership
403  }
404
405  std::unique_ptr<mm1::ModemModem3gppProxyInterface> modem_3gpp_proxy_;
406  std::unique_ptr<mm1::ModemProxyInterface> modem_proxy_;
407  std::unique_ptr<mm1::ModemSimpleProxyInterface> modem_simple_proxy_;
408  std::unique_ptr<mm1::SimProxyInterface> sim_proxy_;
409  // Used to enrich information about the network operator in |ParseScanResult|.
410  // TODO(pprabhu) Instead instantiate a local |MobileOperatorInfo| instance
411  // once the context has been separated out. (crbug.com/363874)
412  std::unique_ptr<MobileOperatorInfo> mobile_operator_info_;
413
414  base::WeakPtrFactory<CellularCapabilityUniversal> weak_ptr_factory_;
415
416  MMModem3gppRegistrationState registration_state_;
417
418  // Bits based on MMModemCapabilities
419  std::vector<uint32_t> supported_capabilities_;  // Technologies supported
420  uint32_t current_capabilities_;  // Technologies supported without a reload
421  uint32_t access_technologies_;   // Bits based on MMModemAccessTechnology
422  std::vector<ModemModes> supported_modes_;
423  ModemModes current_modes_;
424
425  Stringmap serving_operator_;
426  std::string spn_;
427  std::string desired_network_;
428
429  // Properties.
430  std::deque<Stringmap> apn_try_list_;
431  bool resetting_;
432  SimLockStatus sim_lock_status_;
433  SubscriptionState subscription_state_;
434  std::string sim_path_;
435  std::unique_ptr<CellularBearer> active_bearer_;
436  RpcIdentifiers bearer_paths_;
437  bool reset_done_;
438
439  // If the modem is not in a state to be enabled when StartModem is called,
440  // enabling is deferred using this callback.
441  base::Closure deferred_enable_modem_callback_;
442
443  // Sometimes flaky cellular network causes the 3GPP registration state to
444  // rapidly change from registered --> searching and back. Delay such updates
445  // a little to smooth over temporary registration loss.
446  base::CancelableClosure registration_dropped_update_callback_;
447  int64_t registration_dropped_update_timeout_milliseconds_;
448
449  DISALLOW_COPY_AND_ASSIGN(CellularCapabilityUniversal);
450};
451
452}  // namespace shill
453
454#endif  // SHILL_CELLULAR_CELLULAR_CAPABILITY_UNIVERSAL_H_
455