| # Copyright (c) 2012 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. |
| |
| import logging |
| |
| import pm_errors |
| import state_machine |
| |
| from autotest_lib.client.cros.cellular import mm1_constants |
| |
| class DisableMachine(state_machine.StateMachine): |
| """ |
| DisableMachine handles the state transitions involved in bringing the modem |
| to the DISABLED state. |
| |
| """ |
| def __init__(self, modem, return_cb, raise_cb): |
| super(DisableMachine, self).__init__(modem) |
| self.return_cb = return_cb |
| self.raise_cb = raise_cb |
| |
| |
| def _HandleConnectedState(self): |
| logging.info('DisableMachine: Modem is CONNECTED.') |
| assert self._modem.connect_step is None |
| # TODO(armansito): Pass a different raise_cb here to handle |
| # disconnect failure |
| logging.info('DisableMachine: Starting Disconnect.') |
| self._modem.Disconnect(mm1_constants.ROOT_PATH, DisableMachine.Step, |
| DisableMachine.Step, self) |
| return True |
| |
| |
| def _HandleConnectingState(self): |
| logging.info('DisableMachine: Modem is CONNECTING.') |
| assert self._modem.connect_step |
| logging.info('DisableMachine: Canceling connect.') |
| self._modem.connect_step.Cancel() |
| return True |
| |
| |
| def _HandleDisconnectingState(self): |
| logging.info('DisableMachine: Modem is DISCONNECTING.') |
| assert self._modem.disconnect_step |
| logging.info('DisableMachine: Waiting for disconnect.') |
| # wait until disconnect ends |
| return True |
| |
| |
| def _HandleRegisteredState(self): |
| logging.info('DisableMachine: Modem is REGISTERED.') |
| assert not self._modem.IsPendingRegister() |
| assert not self._modem.IsPendingEnable() |
| assert not self._modem.IsPendingConnect() |
| assert not self._modem.IsPendingDisconnect() |
| self._modem.UnregisterWithNetwork() |
| logging.info('DisableMachine: Setting state to DISABLING.') |
| reason = mm1_constants.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED |
| self._modem.ChangeState(mm1_constants.MM_MODEM_STATE_DISABLING, reason) |
| return True |
| |
| |
| def _HandleSearchingState(self): |
| logging.info('DisableMachine: Modem is SEARCHING.') |
| assert self._modem.register_step |
| assert not self._modem.IsPendingEnable() |
| assert not self._modem.IsPendingConnect() |
| logging.info('DisableMachine: Canceling register.') |
| self._modem.register_step.Cancel() |
| return True |
| |
| |
| def _HandleEnabledState(self): |
| logging.info('DisableMachine: Modem is ENABLED.') |
| assert not self._modem.IsPendingRegister() |
| assert not self._modem.IsPendingEnable() |
| assert not self._modem.IsPendingConnect() |
| logging.info('DisableMachine: Setting state to DISABLING.') |
| reason = mm1_constants.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED |
| self._modem.ChangeState(mm1_constants.MM_MODEM_STATE_DISABLING, reason) |
| return True |
| |
| |
| def _HandleDisablingState(self): |
| logging.info('DisableMachine: Modem is DISABLING.') |
| assert not self._modem.IsPendingRegister() |
| assert not self._modem.IsPendingEnable() |
| assert not self._modem.IsPendingConnect() |
| assert not self._modem.IsPendingDisconnect() |
| logging.info('DisableMachine: Setting state to DISABLED.') |
| reason = mm1_constants.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED |
| self._modem.ChangeState(mm1_constants.MM_MODEM_STATE_DISABLED, reason) |
| self._modem.disable_step = None |
| if self.return_cb: |
| self.return_cb() |
| return False |
| |
| |
| def _GetModemStateFunctionMap(self): |
| return { |
| mm1_constants.MM_MODEM_STATE_CONNECTED: |
| DisableMachine._HandleConnectedState, |
| mm1_constants.MM_MODEM_STATE_CONNECTING: |
| DisableMachine._HandleConnectingState, |
| mm1_constants.MM_MODEM_STATE_DISCONNECTING: |
| DisableMachine._HandleDisconnectingState, |
| mm1_constants.MM_MODEM_STATE_REGISTERED: |
| DisableMachine._HandleRegisteredState, |
| mm1_constants.MM_MODEM_STATE_SEARCHING: |
| DisableMachine._HandleSearchingState, |
| mm1_constants.MM_MODEM_STATE_ENABLED: |
| DisableMachine._HandleEnabledState, |
| mm1_constants.MM_MODEM_STATE_DISABLING: |
| DisableMachine._HandleDisablingState |
| } |
| |
| |
| def _ShouldStartStateMachine(self): |
| if self._modem.disable_step and self._modem.disable_step != self: |
| # There is already a disable operation in progress. |
| message = 'Modem disable already in progress.' |
| logging.info(message) |
| raise pm_errors.MMCoreError(pm_errors.MMCoreError.IN_PROGRESS, |
| message) |
| elif self._modem.disable_step is None: |
| # There is no disable operation going in, cancelled or otherwise. |
| state = self._modem.Get(mm1_constants.I_MODEM, 'State') |
| if state == mm1_constants.MM_MODEM_STATE_DISABLED: |
| # The reason we're not raising an error here is that |
| # shill will make multiple successive calls to disable |
| # but WON'T check for raised errors, which causes |
| # problems. Treat this particular case as success. |
| logging.info('Already in a disabled state. Ignoring.') |
| if self.return_cb: |
| self.return_cb() |
| return False |
| |
| invalid_states = [ |
| mm1_constants.MM_MODEM_STATE_FAILED, |
| mm1_constants.MM_MODEM_STATE_UNKNOWN, |
| mm1_constants.MM_MODEM_STATE_INITIALIZING, |
| mm1_constants.MM_MODEM_STATE_LOCKED |
| ] |
| if state in invalid_states: |
| raise pm_errors.MMCoreError( |
| pm_errors.MMCoreError.WRONG_STATE, |
| ('Modem disable cannot be initiated while in state' |
| ' %u.') % state) |
| if self._modem.connect_step: |
| logging.info('There is an ongoing Connect, canceling it.') |
| self._modem.connect_step.Cancel() |
| if self._modem.register_step: |
| logging.info('There is an ongoing Register, canceling it.') |
| self._modem.register_step.Cancel() |
| if self._modem.enable_step: |
| # This needs to be done here, because the case where an enable |
| # cycle has been initiated but it hasn't triggered any state |
| # transitions yet would not be detected in a state handler. |
| logging.info('There is an ongoing Enable, canceling it.') |
| logging.info('This should bring the modem to a disabled state.' |
| ' DisableMachine will not start.') |
| self._modem.enable_step.Cancel() |
| assert self._modem.Get(mm1_constants.I_MODEM, 'State') == \ |
| mm1_constants.MM_MODEM_STATE_DISABLED |
| if self._modem.Get(mm1_constants.I_MODEM, 'State') == \ |
| mm1_constants.MM_MODEM_STATE_DISABLED: |
| if self.return_cb: |
| self.return_cb() |
| return False |
| |
| logging.info('Starting Disable.') |
| self._modem.disable_step = self |
| return True |