1# Copyright (c) 2012 The Chromium OS 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 5import logging 6 7from . import pm_errors 8from . import state_machine 9 10import common 11 12from autotest_lib.client.cros.cellular import mm1_constants 13 14class DisableMachine(state_machine.StateMachine): 15 """ 16 DisableMachine handles the state transitions involved in bringing the modem 17 to the DISABLED state. 18 19 """ 20 def __init__(self, modem, return_cb, raise_cb): 21 super(DisableMachine, self).__init__(modem) 22 self.return_cb = return_cb 23 self.raise_cb = raise_cb 24 25 26 def _HandleConnectedState(self): 27 logging.info('DisableMachine: Modem is CONNECTED.') 28 assert self._modem.connect_step is None 29 # TODO(armansito): Pass a different raise_cb here to handle 30 # disconnect failure 31 logging.info('DisableMachine: Starting Disconnect.') 32 self._modem.Disconnect(mm1_constants.ROOT_PATH, DisableMachine.Step, 33 DisableMachine.Step, self) 34 return True 35 36 37 def _HandleConnectingState(self): 38 logging.info('DisableMachine: Modem is CONNECTING.') 39 assert self._modem.connect_step 40 logging.info('DisableMachine: Canceling connect.') 41 self._modem.connect_step.Cancel() 42 return True 43 44 45 def _HandleDisconnectingState(self): 46 logging.info('DisableMachine: Modem is DISCONNECTING.') 47 assert self._modem.disconnect_step 48 logging.info('DisableMachine: Waiting for disconnect.') 49 # wait until disconnect ends 50 return True 51 52 53 def _HandleRegisteredState(self): 54 logging.info('DisableMachine: Modem is REGISTERED.') 55 assert not self._modem.IsPendingRegister() 56 assert not self._modem.IsPendingEnable() 57 assert not self._modem.IsPendingConnect() 58 assert not self._modem.IsPendingDisconnect() 59 self._modem.UnregisterWithNetwork() 60 logging.info('DisableMachine: Setting state to DISABLING.') 61 reason = mm1_constants.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED 62 self._modem.ChangeState(mm1_constants.MM_MODEM_STATE_DISABLING, reason) 63 return True 64 65 66 def _HandleSearchingState(self): 67 logging.info('DisableMachine: Modem is SEARCHING.') 68 assert self._modem.register_step 69 assert not self._modem.IsPendingEnable() 70 assert not self._modem.IsPendingConnect() 71 logging.info('DisableMachine: Canceling register.') 72 self._modem.register_step.Cancel() 73 return True 74 75 76 def _HandleEnabledState(self): 77 logging.info('DisableMachine: Modem is ENABLED.') 78 assert not self._modem.IsPendingRegister() 79 assert not self._modem.IsPendingEnable() 80 assert not self._modem.IsPendingConnect() 81 logging.info('DisableMachine: Setting state to DISABLING.') 82 reason = mm1_constants.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED 83 self._modem.ChangeState(mm1_constants.MM_MODEM_STATE_DISABLING, reason) 84 return True 85 86 87 def _HandleDisablingState(self): 88 logging.info('DisableMachine: Modem is DISABLING.') 89 assert not self._modem.IsPendingRegister() 90 assert not self._modem.IsPendingEnable() 91 assert not self._modem.IsPendingConnect() 92 assert not self._modem.IsPendingDisconnect() 93 logging.info('DisableMachine: Setting state to DISABLED.') 94 reason = mm1_constants.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED 95 self._modem.ChangeState(mm1_constants.MM_MODEM_STATE_DISABLED, reason) 96 self._modem.disable_step = None 97 if self.return_cb: 98 self.return_cb() 99 return False 100 101 102 def _GetModemStateFunctionMap(self): 103 return { 104 mm1_constants.MM_MODEM_STATE_CONNECTED: 105 DisableMachine._HandleConnectedState, 106 mm1_constants.MM_MODEM_STATE_CONNECTING: 107 DisableMachine._HandleConnectingState, 108 mm1_constants.MM_MODEM_STATE_DISCONNECTING: 109 DisableMachine._HandleDisconnectingState, 110 mm1_constants.MM_MODEM_STATE_REGISTERED: 111 DisableMachine._HandleRegisteredState, 112 mm1_constants.MM_MODEM_STATE_SEARCHING: 113 DisableMachine._HandleSearchingState, 114 mm1_constants.MM_MODEM_STATE_ENABLED: 115 DisableMachine._HandleEnabledState, 116 mm1_constants.MM_MODEM_STATE_DISABLING: 117 DisableMachine._HandleDisablingState 118 } 119 120 121 def _ShouldStartStateMachine(self): 122 if self._modem.disable_step and self._modem.disable_step != self: 123 # There is already a disable operation in progress. 124 message = 'Modem disable already in progress.' 125 logging.info(message) 126 raise pm_errors.MMCoreError(pm_errors.MMCoreError.IN_PROGRESS, 127 message) 128 elif self._modem.disable_step is None: 129 # There is no disable operation going in, cancelled or otherwise. 130 state = self._modem.Get(mm1_constants.I_MODEM, 'State') 131 if state == mm1_constants.MM_MODEM_STATE_DISABLED: 132 # The reason we're not raising an error here is that 133 # shill will make multiple successive calls to disable 134 # but WON'T check for raised errors, which causes 135 # problems. Treat this particular case as success. 136 logging.info('Already in a disabled state. Ignoring.') 137 if self.return_cb: 138 self.return_cb() 139 return False 140 141 invalid_states = [ 142 mm1_constants.MM_MODEM_STATE_FAILED, 143 mm1_constants.MM_MODEM_STATE_UNKNOWN, 144 mm1_constants.MM_MODEM_STATE_INITIALIZING, 145 mm1_constants.MM_MODEM_STATE_LOCKED 146 ] 147 if state in invalid_states: 148 raise pm_errors.MMCoreError( 149 pm_errors.MMCoreError.WRONG_STATE, 150 ('Modem disable cannot be initiated while in state' 151 ' %u.') % state) 152 if self._modem.connect_step: 153 logging.info('There is an ongoing Connect, canceling it.') 154 self._modem.connect_step.Cancel() 155 if self._modem.register_step: 156 logging.info('There is an ongoing Register, canceling it.') 157 self._modem.register_step.Cancel() 158 if self._modem.enable_step: 159 # This needs to be done here, because the case where an enable 160 # cycle has been initiated but it hasn't triggered any state 161 # transitions yet would not be detected in a state handler. 162 logging.info('There is an ongoing Enable, canceling it.') 163 logging.info('This should bring the modem to a disabled state.' 164 ' DisableMachine will not start.') 165 self._modem.enable_step.Cancel() 166 assert self._modem.Get(mm1_constants.I_MODEM, 'State') == \ 167 mm1_constants.MM_MODEM_STATE_DISABLED 168 if self._modem.Get(mm1_constants.I_MODEM, 'State') == \ 169 mm1_constants.MM_MODEM_STATE_DISABLED: 170 if self.return_cb: 171 self.return_cb() 172 return False 173 174 logging.info('Starting Disable.') 175 self._modem.disable_step = self 176 return True 177