ota_activator_impl.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/services/cellular_setup/ota_activator_impl.h"
  5. #include <sstream>
  6. #include "base/bind.h"
  7. #include "base/callback_helpers.h"
  8. #include "base/logging.h"
  9. #include "base/memory/ptr_util.h"
  10. #include "base/metrics/histogram_functions.h"
  11. #include "chromeos/ash/components/dbus/shill/shill_device_client.h"
  12. #include "chromeos/ash/components/network/cellular_utils.h"
  13. #include "chromeos/ash/components/network/device_state.h"
  14. #include "chromeos/ash/components/network/network_activation_handler.h"
  15. #include "chromeos/ash/components/network/network_connection_handler.h"
  16. #include "chromeos/ash/components/network/network_event_log.h"
  17. #include "chromeos/ash/components/network/network_state.h"
  18. #include "chromeos/ash/components/network/network_state_handler.h"
  19. #include "chromeos/ash/components/network/network_util.h"
  20. #include "dbus/object_path.h"
  21. #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
  22. #include "url/gurl.h"
  23. namespace ash::cellular_setup {
  24. namespace {
  25. OtaActivatorImpl::Factory* g_test_factory = nullptr;
  26. void OnModemResetError(const std::string& error_name,
  27. const std::string& error_message) {
  28. NET_LOG(ERROR) << "ShillDeviceClient::Reset() failed. " << error_name << ": "
  29. << error_message << ".";
  30. }
  31. } // namespace
  32. // static
  33. std::unique_ptr<OtaActivator> OtaActivatorImpl::Factory::Create(
  34. mojo::PendingRemote<mojom::ActivationDelegate> activation_delegate,
  35. base::OnceClosure on_finished_callback,
  36. NetworkStateHandler* network_state_handler,
  37. NetworkConnectionHandler* network_connection_handler,
  38. NetworkActivationHandler* network_activation_handler,
  39. scoped_refptr<base::TaskRunner> task_runner) {
  40. if (g_test_factory) {
  41. return g_test_factory->CreateInstance(
  42. std::move(activation_delegate), std::move(on_finished_callback),
  43. network_state_handler, network_connection_handler,
  44. network_activation_handler, std::move(task_runner));
  45. }
  46. return base::WrapUnique(new OtaActivatorImpl(
  47. std::move(activation_delegate), std::move(on_finished_callback),
  48. network_state_handler, network_connection_handler,
  49. network_activation_handler, std::move(task_runner)));
  50. }
  51. // static
  52. void OtaActivatorImpl::Factory::SetFactoryForTesting(Factory* test_factory) {
  53. g_test_factory = test_factory;
  54. }
  55. OtaActivatorImpl::Factory::~Factory() = default;
  56. // static
  57. const base::TimeDelta OtaActivatorImpl::kConnectRetryDelay = base::Seconds(3);
  58. // static
  59. const size_t OtaActivatorImpl::kMaxConnectRetryAttempt = 3;
  60. OtaActivatorImpl::OtaActivatorImpl(
  61. mojo::PendingRemote<mojom::ActivationDelegate> activation_delegate,
  62. base::OnceClosure on_finished_callback,
  63. NetworkStateHandler* network_state_handler,
  64. NetworkConnectionHandler* network_connection_handler,
  65. NetworkActivationHandler* network_activation_handler,
  66. scoped_refptr<base::TaskRunner> task_runner)
  67. : OtaActivator(std::move(on_finished_callback)),
  68. activation_delegate_(std::move(activation_delegate)),
  69. network_state_handler_(network_state_handler),
  70. network_connection_handler_(network_connection_handler),
  71. network_activation_handler_(network_activation_handler) {
  72. task_runner->PostTask(FROM_HERE,
  73. base::BindOnce(&OtaActivatorImpl::StartActivation,
  74. weak_ptr_factory_.GetWeakPtr()));
  75. }
  76. OtaActivatorImpl::~OtaActivatorImpl() {
  77. // If this object is being deleted but it never finished the flow, consider
  78. // this a failure.
  79. if (state_ != State::kFinished)
  80. FinishActivationAttempt(mojom::ActivationResult::kFailedToActivate);
  81. }
  82. void OtaActivatorImpl::OnCarrierPortalStatusChange(
  83. mojom::CarrierPortalStatus status) {
  84. if (last_carrier_portal_status_) {
  85. NET_LOG(USER) << "OtaActivatorImpl: Carrier portal status updated. "
  86. << *last_carrier_portal_status_ << " => " << status;
  87. } else {
  88. NET_LOG(USER) << "OtaActivatorImpl: Carrier portal status updated. "
  89. << "Status: " << status;
  90. }
  91. last_carrier_portal_status_ = status;
  92. AttemptNextActivationStep();
  93. }
  94. void OtaActivatorImpl::NetworkListChanged() {
  95. AttemptNextActivationStep();
  96. }
  97. void OtaActivatorImpl::DeviceListChanged() {
  98. AttemptNextActivationStep();
  99. }
  100. void OtaActivatorImpl::NetworkPropertiesUpdated(const NetworkState* network) {
  101. AttemptNextActivationStep();
  102. }
  103. void OtaActivatorImpl::DevicePropertiesUpdated(const DeviceState* device) {
  104. AttemptNextActivationStep();
  105. }
  106. void OtaActivatorImpl::OnShuttingDown() {
  107. // |network_state_handler_| is shutting down before activation was able to
  108. // complete.
  109. FinishActivationAttempt(mojom::ActivationResult::kFailedToActivate);
  110. }
  111. const DeviceState* OtaActivatorImpl::GetCellularDeviceState() const {
  112. return network_state_handler_->GetDeviceStateByType(
  113. NetworkTypePattern::Cellular());
  114. }
  115. const NetworkState* OtaActivatorImpl::GetCellularNetworkState() const {
  116. NetworkStateHandler::NetworkStateList network_list;
  117. network_state_handler_->GetVisibleNetworkListByType(
  118. NetworkTypePattern::Cellular(), &network_list);
  119. for (const NetworkState* network_state : network_list) {
  120. if (network_state->iccid() == iccid_) {
  121. return network_state;
  122. }
  123. }
  124. return nullptr;
  125. }
  126. void OtaActivatorImpl::StartActivation() {
  127. network_state_handler_->AddObserver(this, FROM_HERE);
  128. // If |activation_delegate_| becomes disconnected, the activation request is
  129. // considered canceled.
  130. activation_delegate_.set_disconnect_handler(base::BindOnce(
  131. &OtaActivatorImpl::FinishActivationAttempt, base::Unretained(this),
  132. mojom::ActivationResult::kFailedToActivate));
  133. ChangeStateAndAttemptNextStep(State::kWaitingForValidSimToBecomePresent);
  134. }
  135. void OtaActivatorImpl::ChangeStateAndAttemptNextStep(State state) {
  136. DCHECK_NE(state, state_);
  137. NET_LOG(DEBUG) << "OtaActivatorImpl: " << state_ << " => " << state << ".";
  138. state_ = state;
  139. AttemptNextActivationStep();
  140. }
  141. void OtaActivatorImpl::AttemptNextActivationStep() {
  142. switch (state_) {
  143. case State::kNotYetStarted:
  144. // The flow either has not yet started; nothing to do.
  145. break;
  146. case State::kWaitingForValidSimToBecomePresent:
  147. AttemptToDiscoverSim();
  148. break;
  149. case State::kWaitingForCellularConnection:
  150. AttemptConnectionToCellularNetwork();
  151. break;
  152. case State::kWaitingForCellularPayment:
  153. AttemptToSendMetadataToDelegate();
  154. break;
  155. case State::kWaitingForActivation:
  156. AttemptToCompleteActivation();
  157. break;
  158. case State::kFinished:
  159. InvokeOnFinishedCallback();
  160. break;
  161. }
  162. }
  163. void OtaActivatorImpl::FinishActivationAttempt(
  164. mojom::ActivationResult activation_result) {
  165. DCHECK(network_state_handler_);
  166. network_state_handler_->RemoveObserver(this, FROM_HERE);
  167. network_state_handler_ = nullptr;
  168. NET_LOG(EVENT) << "Finished attempt with result " << activation_result << ".";
  169. base::UmaHistogramEnumeration("Network.Cellular.PSim.OtaActivationResult",
  170. activation_result);
  171. if (activation_delegate_)
  172. activation_delegate_->OnActivationFinished(activation_result);
  173. ChangeStateAndAttemptNextStep(State::kFinished);
  174. }
  175. void OtaActivatorImpl::AttemptToDiscoverSim() {
  176. DCHECK(state_ == State::kWaitingForValidSimToBecomePresent);
  177. const DeviceState* cellular_device = GetCellularDeviceState();
  178. // If the Cellular device is not present, either this machine does not support
  179. // cellular connections or the modem on the device is in the process of
  180. // restarting.
  181. if (!cellular_device)
  182. return;
  183. // Find status of first available pSIM slot.
  184. // Note: We currently only support setting up devices with single physical
  185. // SIM slots. This excludes other configurations such as multiple physical
  186. // SIM slots and SIM cards in external dongles.
  187. bool has_psim_slots = false;
  188. for (const CellularSIMSlotInfo& sim_slot_info :
  189. GetSimSlotInfosWithUpdatedEid(cellular_device)) {
  190. if (sim_slot_info.eid.empty()) {
  191. has_psim_slots = true;
  192. iccid_ = sim_slot_info.iccid;
  193. break;
  194. }
  195. }
  196. if (!has_psim_slots) {
  197. NET_LOG(ERROR) << "No PSim slots found";
  198. FinishActivationAttempt(mojom::ActivationResult::kFailedToActivate);
  199. return;
  200. }
  201. // If no SIM card is present, it may be due to the fact that some devices do
  202. // not have hardware support for determining whether a SIM has been inserted.
  203. // Restart the modem to see if the SIM is detected when the modem powers back
  204. // on.
  205. if (iccid_.empty()) {
  206. NET_LOG(DEBUG) << "No SIM detected; restarting modem.";
  207. ShillDeviceClient::Get()->Reset(
  208. dbus::ObjectPath(cellular_device->path()),
  209. base::BindOnce(&OtaActivatorImpl::AttemptNextActivationStep,
  210. weak_ptr_factory_.GetWeakPtr()),
  211. base::BindOnce(&OnModemResetError));
  212. return;
  213. }
  214. ChangeStateAndAttemptNextStep(State::kWaitingForCellularConnection);
  215. }
  216. void OtaActivatorImpl::AttemptConnectionToCellularNetwork() {
  217. DCHECK(state_ == State::kWaitingForCellularConnection);
  218. const NetworkState* cellular_network = GetCellularNetworkState();
  219. // There is no cellular network to be connected; return early and wait for
  220. // NetworkListChanged() to be called if/when one becomes available.
  221. if (!cellular_network)
  222. return;
  223. // The network is disconnected; trigger a connection and wait for
  224. // NetworkPropertiesUpdated() to be called when the network connects.
  225. if (!cellular_network->IsConnectingOrConnected()) {
  226. if (connect_retry_timer_.IsRunning()) {
  227. return;
  228. }
  229. network_connection_handler_->ConnectToNetwork(
  230. cellular_network->path(), base::DoNothing(),
  231. base::BindOnce(&OtaActivatorImpl::OnNetworkConnectionError,
  232. weak_ptr_factory_.GetWeakPtr()),
  233. false /* check_error_state */, ConnectCallbackMode::ON_COMPLETED);
  234. return;
  235. }
  236. // The network is connecting; return early and wait for
  237. // NetworkPropertiesUpdated() to be called if/when the network connects.
  238. if (cellular_network->IsConnectingState())
  239. return;
  240. connect_retry_timer_.Stop();
  241. // If the network is already activated, there is no need to complete the rest
  242. // of the flow.
  243. if (cellular_network->activation_state() ==
  244. shill::kActivationStateActivated) {
  245. FinishActivationAttempt(mojom::ActivationResult::kAlreadyActivated);
  246. return;
  247. }
  248. const DeviceState* cellular_device = GetCellularDeviceState();
  249. // The device must have the properties required for the actication flow;
  250. // namely, the operator name and IMEI. Return and wait to see if
  251. // DevicePropertiesUpdated() is invoked with valid properties.
  252. if (cellular_device->operator_name().empty() ||
  253. cellular_device->imei().empty()) {
  254. NET_LOG(DEBUG) << "Insufficient activation data: "
  255. << "Operator name: " << cellular_device->operator_name()
  256. << ", IMEI: " << cellular_device->imei();
  257. return;
  258. }
  259. // The network must have payment information; at minimum, a payment URL is
  260. // required in order to contact the carrier payment portal. Return and wait to
  261. // see if NetworkPropertiesUpdated() is invoked with valid properties.
  262. if (cellular_network->payment_url().empty()) {
  263. NET_LOG(DEBUG) << "Insufficient activation data: "
  264. << "Payment URL: " << cellular_network->payment_url() << ", "
  265. << "Post Data: " << cellular_network->payment_post_data();
  266. return;
  267. }
  268. ChangeStateAndAttemptNextStep(State::kWaitingForCellularPayment);
  269. }
  270. void OtaActivatorImpl::AttemptToSendMetadataToDelegate() {
  271. DCHECK(state_ == State::kWaitingForCellularPayment);
  272. // Metadata should only be sent to the delegate once.
  273. if (!has_sent_metadata_) {
  274. has_sent_metadata_ = true;
  275. const DeviceState* cellular_device = GetCellularDeviceState();
  276. const NetworkState* cellular_network = GetCellularNetworkState();
  277. NET_LOG(DEBUG) << "Sending CellularMetadata. "
  278. << "Payment URL: " << cellular_network->payment_url() << ", "
  279. << "Post data: " << cellular_network->payment_post_data()
  280. << ", Carrier: " << cellular_device->operator_name() << ", "
  281. << "MEID: " << cellular_device->meid() << ", "
  282. << "IMEI: " << cellular_device->imei() << ", "
  283. << "MDN: " << cellular_device->mdn();
  284. activation_delegate_->OnActivationStarted(mojom::CellularMetadata::New(
  285. GURL(cellular_network->payment_url()),
  286. cellular_network->payment_post_data(), cellular_device->operator_name(),
  287. cellular_device->meid(), cellular_device->imei(),
  288. cellular_device->mdn()));
  289. }
  290. // The user must successfully pay via the carrier portal before continuing.
  291. // The carrier portal may also load but fail to notify the UI of payment
  292. // success. The UI will send kPortalLoadedButErrorOccurredDuringPayment
  293. // in this case. Optimistically complete activation in case the user did
  294. // complete payment.
  295. if (last_carrier_portal_status_ !=
  296. mojom::CarrierPortalStatus::kPortalLoadedAndUserCompletedPayment &&
  297. last_carrier_portal_status_ !=
  298. mojom::CarrierPortalStatus::
  299. kPortalLoadedButErrorOccurredDuringPayment) {
  300. return;
  301. }
  302. ChangeStateAndAttemptNextStep(State::kWaitingForActivation);
  303. }
  304. void OtaActivatorImpl::AttemptToCompleteActivation() {
  305. DCHECK(state_ == State::kWaitingForActivation);
  306. // CompleteActivation() should only be called once.
  307. if (has_called_complete_activation_)
  308. return;
  309. has_called_complete_activation_ = true;
  310. network_activation_handler_->CompleteActivation(
  311. GetCellularNetworkState()->path(),
  312. base::BindOnce(&OtaActivatorImpl::FinishActivationAttempt,
  313. weak_ptr_factory_.GetWeakPtr(),
  314. mojom::ActivationResult::kSuccessfullyStartedActivation),
  315. base::BindOnce(&OtaActivatorImpl::OnCompleteActivationError,
  316. weak_ptr_factory_.GetWeakPtr()));
  317. }
  318. void OtaActivatorImpl::OnCompleteActivationError(
  319. const std::string& error_name) {
  320. NET_LOG(ERROR) << "CompleteActivation() failed. Error name: " << error_name;
  321. FinishActivationAttempt(mojom::ActivationResult::kFailedToActivate);
  322. }
  323. void OtaActivatorImpl::OnNetworkConnectionError(const std::string& error_name) {
  324. if (connect_retry_attempts_ >= kMaxConnectRetryAttempt) {
  325. NET_LOG(ERROR) << "Reached max connection retry attempts.";
  326. FinishActivationAttempt(mojom::ActivationResult::kFailedToActivate);
  327. return;
  328. }
  329. base::TimeDelta retry_delay =
  330. kConnectRetryDelay * (1 << connect_retry_attempts_);
  331. connect_retry_attempts_++;
  332. NET_LOG(DEBUG) << "Network connect for activation failed. Error="
  333. << error_name << ". Retrying in " << retry_delay;
  334. connect_retry_timer_.Start(
  335. FROM_HERE, retry_delay,
  336. base::BindOnce(&OtaActivatorImpl::AttemptNextActivationStep,
  337. weak_ptr_factory_.GetWeakPtr()));
  338. }
  339. void OtaActivatorImpl::FlushForTesting() {
  340. if (activation_delegate_)
  341. activation_delegate_.FlushForTesting();
  342. }
  343. std::ostream& operator<<(std::ostream& stream,
  344. const OtaActivatorImpl::State& state) {
  345. switch (state) {
  346. case OtaActivatorImpl::State::kNotYetStarted:
  347. stream << "[Not yet started]";
  348. break;
  349. case OtaActivatorImpl::State::kWaitingForValidSimToBecomePresent:
  350. stream << "[Waiting for SIM to become present]";
  351. break;
  352. case OtaActivatorImpl::State::kWaitingForCellularConnection:
  353. stream << "[Waiting for connected cellular network]";
  354. break;
  355. case OtaActivatorImpl::State::kWaitingForCellularPayment:
  356. stream << "[Waiting cellular payment payment to complete]";
  357. break;
  358. case OtaActivatorImpl::State::kWaitingForActivation:
  359. stream << "[Waiting for Shill activation to complete]";
  360. break;
  361. case OtaActivatorImpl::State::kFinished:
  362. stream << "[Finished]";
  363. break;
  364. }
  365. return stream;
  366. }
  367. } // namespace ash::cellular_setup