1be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# Copyright 2014 The Chromium Authors. All rights reserved.
2be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# Use of this source code is governed by a BSD-style license that can be
3be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# found in the LICENSE file.
4be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
5be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik"""
6be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris CraikException classes raised by AdbWrapper and DeviceUtils.
7576fd2a645575980f16b6731dab0f4f150100657Chris Craik
8576fd2a645575980f16b6731dab0f4f150100657Chris CraikThe class hierarchy for device exceptions is:
9576fd2a645575980f16b6731dab0f4f150100657Chris Craik
10576fd2a645575980f16b6731dab0f4f150100657Chris Craik    base_error.BaseError
11576fd2a645575980f16b6731dab0f4f150100657Chris Craik     +-- CommandFailedError
12576fd2a645575980f16b6731dab0f4f150100657Chris Craik     |    +-- AdbCommandFailedError
13576fd2a645575980f16b6731dab0f4f150100657Chris Craik     |    |    +-- AdbShellCommandFailedError
14576fd2a645575980f16b6731dab0f4f150100657Chris Craik     |    +-- FastbootCommandFailedError
15576fd2a645575980f16b6731dab0f4f150100657Chris Craik     |    +-- DeviceVersionError
16576fd2a645575980f16b6731dab0f4f150100657Chris Craik     |    +-- DeviceChargingError
17576fd2a645575980f16b6731dab0f4f150100657Chris Craik     +-- CommandTimeoutError
18576fd2a645575980f16b6731dab0f4f150100657Chris Craik     +-- DeviceUnreachableError
19576fd2a645575980f16b6731dab0f4f150100657Chris Craik     +-- NoDevicesError
20576fd2a645575980f16b6731dab0f4f150100657Chris Craik     +-- MultipleDevicesError
21576fd2a645575980f16b6731dab0f4f150100657Chris Craik     +-- NoAdbError
22576fd2a645575980f16b6731dab0f4f150100657Chris Craik
23be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik"""
24be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
25be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikfrom devil import base_error
26be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikfrom devil.utils import cmd_helper
27a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craikfrom devil.utils import parallelizer
28be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
29be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
30be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikclass CommandFailedError(base_error.BaseError):
31be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """Exception for command failures."""
32be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
33be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def __init__(self, message, device_serial=None):
3433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    device_leader = '(device: %s)' % device_serial
3533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    if device_serial is not None and not message.startswith(device_leader):
3633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      message = '%s %s' % (device_leader, message)
37be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self.device_serial = device_serial
38be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    super(CommandFailedError, self).__init__(message)
39be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
4033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def __eq__(self, other):
4133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return (super(CommandFailedError, self).__eq__(other)
4233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            and self.device_serial == other.device_serial)
4333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
4433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def __ne__(self, other):
4533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return not self == other
4633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
47be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
48be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikclass _BaseCommandFailedError(CommandFailedError):
49be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """Base Exception for adb and fastboot command failures."""
50be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
51be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def __init__(self, args, output, status=None, device_serial=None,
52be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik               message=None):
53be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self.args = args
54be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self.output = output
55be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self.status = status
56be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if not message:
57be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      adb_cmd = ' '.join(cmd_helper.SingleQuote(arg) for arg in self.args)
58be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      message = ['adb %s: failed ' % adb_cmd]
59be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      if status:
60be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        message.append('with exit status %s ' % self.status)
61be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      if output:
62be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        message.append('and output:\n')
63be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        message.extend('- %s\n' % line for line in output.splitlines())
64be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      else:
65be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        message.append('and no output.')
66be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      message = ''.join(message)
67be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    super(_BaseCommandFailedError, self).__init__(message, device_serial)
68be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
6933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def __eq__(self, other):
7033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return (super(_BaseCommandFailedError, self).__eq__(other)
7133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            and self.args == other.args
7233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            and self.output == other.output
7333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            and self.status == other.status)
7433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
7533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def __ne__(self, other):
7633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return not self == other
7733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
7833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def __reduce__(self):
7933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """Support pickling."""
8033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    result = [None, None, None, None, None]
8133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    super_result = super(_BaseCommandFailedError, self).__reduce__()
8233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in range(len(super_result)):
8333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      result[i] = super_result[i]
8433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
8533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Update the args used to reconstruct this exception.
8633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    result[1] = (
8733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        self.args, self.output, self.status, self.device_serial, self.message)
8833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return tuple(result)
8933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
90be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
91be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikclass AdbCommandFailedError(_BaseCommandFailedError):
92be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """Exception for adb command failures."""
93be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
94be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def __init__(self, args, output, status=None, device_serial=None,
95be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik               message=None):
96be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    super(AdbCommandFailedError, self).__init__(
97be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        args, output, status=status, message=message,
98be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        device_serial=device_serial)
99be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
100be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
101be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikclass FastbootCommandFailedError(_BaseCommandFailedError):
102be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """Exception for fastboot command failures."""
103be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
104be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def __init__(self, args, output, status=None, device_serial=None,
105be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik               message=None):
106be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    super(FastbootCommandFailedError, self).__init__(
107be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        args, output, status=status, message=message,
108be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        device_serial=device_serial)
109be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
110be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
111be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikclass DeviceVersionError(CommandFailedError):
112be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """Exception for device version failures."""
113be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
114be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def __init__(self, message, device_serial=None):
115be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    super(DeviceVersionError, self).__init__(message, device_serial)
116be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
117be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
118be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikclass AdbShellCommandFailedError(AdbCommandFailedError):
119be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """Exception for shell command failures run via adb."""
120be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
121be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def __init__(self, command, output, status, device_serial=None):
122be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self.command = command
123be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    message = ['shell command run via adb failed on the device:\n',
124be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik               '  command: %s\n' % command]
125be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    message.append('  exit status: %s\n' % status)
126be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if output:
127be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      message.append('  output:\n')
128be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      if isinstance(output, basestring):
129be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        output_lines = output.splitlines()
130be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      else:
131be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        output_lines = output
132be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      message.extend('  - %s\n' % line for line in output_lines)
133be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    else:
134be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      message.append("  output: ''\n")
135be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    message = ''.join(message)
136be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    super(AdbShellCommandFailedError, self).__init__(
137be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      ['shell', command], output, status, device_serial, message)
138be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
13933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def __reduce__(self):
14033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """Support pickling."""
14133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    result = [None, None, None, None, None]
14233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    super_result = super(AdbShellCommandFailedError, self).__reduce__()
14333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in range(len(super_result)):
14433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      result[i] = super_result[i]
14533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
14633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Update the args used to reconstruct this exception.
14733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    result[1] = (self.command, self.output, self.status, self.device_serial)
14833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return tuple(result)
14933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
150be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
151be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikclass CommandTimeoutError(base_error.BaseError):
152be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """Exception for command timeouts."""
153be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  pass
154be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
155be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
156be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikclass DeviceUnreachableError(base_error.BaseError):
157be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """Exception for device unreachable failures."""
158be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  pass
159be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
160be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
161be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikclass NoDevicesError(base_error.BaseError):
162be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """Exception for having no devices attached."""
163be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
16433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def __init__(self, msg=None):
165be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    super(NoDevicesError, self).__init__(
16633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        msg or 'No devices attached.', is_infra_error=True)
167be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
168be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
169a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craikclass MultipleDevicesError(base_error.BaseError):
170a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  """Exception for having multiple attached devices without selecting one."""
171a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
172a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  def __init__(self, devices):
173a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    parallel_devices = parallelizer.Parallelizer(devices)
174a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    descriptions = parallel_devices.pMap(
175a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik        lambda d: d.build_description).pGet(None)
176a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    msg = ('More than one device available. Use -d/--device to select a device '
177a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik           'by serial.\n\nAvailable devices:\n')
178a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    for d, desc in zip(devices, descriptions):
179a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      msg += '  %s (%s)\n' % (d, desc)
180a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
181a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    super(MultipleDevicesError, self).__init__(msg, is_infra_error=True)
182a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
183a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
184be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikclass NoAdbError(base_error.BaseError):
185be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """Exception for being unable to find ADB."""
186be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
187be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def __init__(self, msg=None):
188be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    super(NoAdbError, self).__init__(
189be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        msg or 'Unable to find adb.', is_infra_error=True)
190be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
191be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
192be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikclass DeviceChargingError(CommandFailedError):
193be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """Exception for device charging errors."""
194be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
195be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def __init__(self, message, device_serial=None):
196be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    super(DeviceChargingError, self).__init__(message, device_serial)
197