We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Exceptions from `CallbackHandler` should include timeout value
Right now some timeout exceptions thrown by `CallbackHandler` do not include how long the timeout was, making debugging more difficult.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mobly/controllers/android_device_lib/callback_handler.py`
Content:
```
1 # Copyright 2017 Google Inc.
2 # 
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 # 
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 # 
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import time
16 
17 from mobly.controllers.android_device_lib import snippet_event
18 
19 # The max timeout cannot be larger than the max time the socket waits for a
20 # response message. Otherwise, the socket would timeout before the Rpc call
21 # does, leaving both server and client in unknown states.
22 MAX_TIMEOUT = 60 * 10
23 DEFAULT_TIMEOUT = 120  # two minutes
24 
25 
26 class Error(Exception):
27     pass
28 
29 
30 class TimeoutError(Error):
31     pass
32 
33 
34 class CallbackHandler(object):
35     """The class used to handle a specific group of callback events.
36 
37     All the events handled by a CallbackHandler are originally triggered by one
38     async Rpc call. All the events are tagged with a callback_id specific to a
39     call to an AsyncRpc method defined on the server side.
40 
41     The raw message representing an event looks like:
42     {
43         'callbackId': <string, callbackId>,
44         'name': <string, name of the event>,
45         'time': <long, epoch time of when the event was created on the server
46                  side>,
47         'data': <dict, extra data from the callback on the server side>
48     }
49 
50     Each message is then used to create a SnippetEvent object on the client
51     side.
52 
53     Attributes:
54         ret_value: The direct return value of the async Rpc call.
55     """
56 
57     def __init__(self, callback_id, event_client, ret_value, method_name):
58         self._id = callback_id
59         self._event_client = event_client
60         self.ret_value = ret_value
61         self._method_name = method_name
62 
63     def waitAndGet(self, event_name, timeout=DEFAULT_TIMEOUT):
64         """Blocks until an event of the specified name has been received and
65         return the event, or timeout.
66 
67         Args:
68             event_name: string, name of the event to get.
69             timeout: float, the number of seconds to wait before giving up.
70 
71         Returns:
72             SnippetEvent, the oldest entry of the specified event.
73 
74         Raises:
75             Error: If the specified timeout is longer than the max timeout
76                    supported.
77             TimeoutError: The expected event does not occur within time limit.
78         """
79         if timeout:
80             if timeout > MAX_TIMEOUT:
81                 raise Error(
82                     'Specified timeout %s is longer than max timeout %s.' %
83                     (timeout, MAX_TIMEOUT))
84             timeout *= 1000  # convert to milliseconds for java side
85         try:
86             raw_event = self._event_client.eventWaitAndGet(self._id,
87                                                            event_name, timeout)
88         except Exception as e:
89             if 'EventSnippetException: timeout.' in str(e):
90                 raise TimeoutError(
91                     'Timeout waiting for event "%s" triggered by %s (%s).' %
92                     (event_name, self._method_name, self._id))
93             raise
94         return snippet_event.from_dict(raw_event)
95 
96     def waitForEvent(self, event_name, predicate, timeout=DEFAULT_TIMEOUT):
97         """Wait for an event of a specific name that satisfies the predicate.
98 
99         This call will block until the expected event has been received or time
100         out.
101 
102         The predicate function defines the condition the event is expected to
103         satisfy. It takes an event and returns True if the condition is
104         satisfied, False otherwise.
105 
106         Note all events of the same name that are received but don't satisfy
107         the predicate will be discarded and not be available for further
108         consumption.
109 
110         Args:
111           event_name: string, the name of the event to wait for.
112           predicate: function, a function that takes an event (dictionary) and
113                      returns a bool.
114           timeout: float, default is 120s.
115 
116         Returns:
117           dictionary, the event that satisfies the predicate if received.
118 
119         Raises:
120           TimeoutError: raised if no event that satisfies the predicate is
121                         received after timeout seconds.
122         """
123         deadline = time.time() + timeout
124         while time.time() <= deadline:
125             # Calculate the max timeout for the next event rpc call.
126             rpc_timeout = deadline - time.time()
127             if rpc_timeout < 0:
128                 break
129             try:
130                 event = self.waitAndGet(event_name, rpc_timeout)
131             except TimeoutError:
132                 # Ignoring TimeoutError since we need to throw one with a more
133                 # specific message.
134                 break
135             if predicate(event):
136                 return event
137         raise TimeoutError(
138             'Timed out after %ss waiting for an "%s" event that satisfies the '
139             'predicate "%s".' % (timeout, event_name, predicate.__name__))
140 
141     def getAll(self, event_name):
142         """Gets all the events of a certain name that have been received so
143         far. This is a non-blocking call.
144 
145         Args:
146             callback_id: The id of the callback.
147             event_name: string, the name of the event to get.
148 
149         Returns:
150             A list of SnippetEvent, each representing an event from the Java
151             side.
152         """
153         raw_events = self._event_client.eventGetAll(self._id, event_name)
154         return [snippet_event.from_dict(msg) for msg in raw_events]
155
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mobly/controllers/android_device_lib/callback_handler.py b/mobly/controllers/android_device_lib/callback_handler.py
--- a/mobly/controllers/android_device_lib/callback_handler.py
+++ b/mobly/controllers/android_device_lib/callback_handler.py
@@ -83,13 +83,14 @@
                     (timeout, MAX_TIMEOUT))
             timeout *= 1000  # convert to milliseconds for java side
         try:
-            raw_event = self._event_client.eventWaitAndGet(self._id,
-                                                           event_name, timeout)
+            raw_event = self._event_client.eventWaitAndGet(
+                self._id, event_name, timeout)
         except Exception as e:
             if 'EventSnippetException: timeout.' in str(e):
                 raise TimeoutError(
-                    'Timeout waiting for event "%s" triggered by %s (%s).' %
-                    (event_name, self._method_name, self._id))
+                    'Timed out after waiting %ss for event "%s" triggered by'
+                    ' %s (%s).' % (timeout, event_name, self._method_name,
+                                   self._id))
             raise
         return snippet_event.from_dict(raw_event)

{"golden_diff": "diff --git a/mobly/controllers/android_device_lib/callback_handler.py b/mobly/controllers/android_device_lib/callback_handler.py\n--- a/mobly/controllers/android_device_lib/callback_handler.py\n+++ b/mobly/controllers/android_device_lib/callback_handler.py\n@@ -83,13 +83,14 @@\n                     (timeout, MAX_TIMEOUT))\n             timeout *= 1000  # convert to milliseconds for java side\n         try:\n-            raw_event = self._event_client.eventWaitAndGet(self._id,\n-                                                           event_name, timeout)\n+            raw_event = self._event_client.eventWaitAndGet(\n+                self._id, event_name, timeout)\n         except Exception as e:\n             if 'EventSnippetException: timeout.' in str(e):\n                 raise TimeoutError(\n-                    'Timeout waiting for event \"%s\" triggered by %s (%s).' %\n-                    (event_name, self._method_name, self._id))\n+                    'Timed out after waiting %ss for event \"%s\" triggered by'\n+                    ' %s (%s).' % (timeout, event_name, self._method_name,\n+                                   self._id))\n             raise\n         return snippet_event.from_dict(raw_event)\n", "issue": "Exceptions from `CallbackHandler` should include timeout value\nRight now some timeout exceptions thrown by `CallbackHandler` do not include how long the timeout was, making debugging more difficult.\n", "before_files": [{"content": "# Copyright 2017 Google Inc.\n# \n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n# \n#     http://www.apache.org/licenses/LICENSE-2.0\n# \n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport time\n\nfrom mobly.controllers.android_device_lib import snippet_event\n\n# The max timeout cannot be larger than the max time the socket waits for a\n# response message. Otherwise, the socket would timeout before the Rpc call\n# does, leaving both server and client in unknown states.\nMAX_TIMEOUT = 60 * 10\nDEFAULT_TIMEOUT = 120  # two minutes\n\n\nclass Error(Exception):\n    pass\n\n\nclass TimeoutError(Error):\n    pass\n\n\nclass CallbackHandler(object):\n    \"\"\"The class used to handle a specific group of callback events.\n\n    All the events handled by a CallbackHandler are originally triggered by one\n    async Rpc call. All the events are tagged with a callback_id specific to a\n    call to an AsyncRpc method defined on the server side.\n\n    The raw message representing an event looks like:\n    {\n        'callbackId': <string, callbackId>,\n        'name': <string, name of the event>,\n        'time': <long, epoch time of when the event was created on the server\n                 side>,\n        'data': <dict, extra data from the callback on the server side>\n    }\n\n    Each message is then used to create a SnippetEvent object on the client\n    side.\n\n    Attributes:\n        ret_value: The direct return value of the async Rpc call.\n    \"\"\"\n\n    def __init__(self, callback_id, event_client, ret_value, method_name):\n        self._id = callback_id\n        self._event_client = event_client\n        self.ret_value = ret_value\n        self._method_name = method_name\n\n    def waitAndGet(self, event_name, timeout=DEFAULT_TIMEOUT):\n        \"\"\"Blocks until an event of the specified name has been received and\n        return the event, or timeout.\n\n        Args:\n            event_name: string, name of the event to get.\n            timeout: float, the number of seconds to wait before giving up.\n\n        Returns:\n            SnippetEvent, the oldest entry of the specified event.\n\n        Raises:\n            Error: If the specified timeout is longer than the max timeout\n                   supported.\n            TimeoutError: The expected event does not occur within time limit.\n        \"\"\"\n        if timeout:\n            if timeout > MAX_TIMEOUT:\n                raise Error(\n                    'Specified timeout %s is longer than max timeout %s.' %\n                    (timeout, MAX_TIMEOUT))\n            timeout *= 1000  # convert to milliseconds for java side\n        try:\n            raw_event = self._event_client.eventWaitAndGet(self._id,\n                                                           event_name, timeout)\n        except Exception as e:\n            if 'EventSnippetException: timeout.' in str(e):\n                raise TimeoutError(\n                    'Timeout waiting for event \"%s\" triggered by %s (%s).' %\n                    (event_name, self._method_name, self._id))\n            raise\n        return snippet_event.from_dict(raw_event)\n\n    def waitForEvent(self, event_name, predicate, timeout=DEFAULT_TIMEOUT):\n        \"\"\"Wait for an event of a specific name that satisfies the predicate.\n\n        This call will block until the expected event has been received or time\n        out.\n\n        The predicate function defines the condition the event is expected to\n        satisfy. It takes an event and returns True if the condition is\n        satisfied, False otherwise.\n\n        Note all events of the same name that are received but don't satisfy\n        the predicate will be discarded and not be available for further\n        consumption.\n\n        Args:\n          event_name: string, the name of the event to wait for.\n          predicate: function, a function that takes an event (dictionary) and\n                     returns a bool.\n          timeout: float, default is 120s.\n\n        Returns:\n          dictionary, the event that satisfies the predicate if received.\n\n        Raises:\n          TimeoutError: raised if no event that satisfies the predicate is\n                        received after timeout seconds.\n        \"\"\"\n        deadline = time.time() + timeout\n        while time.time() <= deadline:\n            # Calculate the max timeout for the next event rpc call.\n            rpc_timeout = deadline - time.time()\n            if rpc_timeout < 0:\n                break\n            try:\n                event = self.waitAndGet(event_name, rpc_timeout)\n            except TimeoutError:\n                # Ignoring TimeoutError since we need to throw one with a more\n                # specific message.\n                break\n            if predicate(event):\n                return event\n        raise TimeoutError(\n            'Timed out after %ss waiting for an \"%s\" event that satisfies the '\n            'predicate \"%s\".' % (timeout, event_name, predicate.__name__))\n\n    def getAll(self, event_name):\n        \"\"\"Gets all the events of a certain name that have been received so\n        far. This is a non-blocking call.\n\n        Args:\n            callback_id: The id of the callback.\n            event_name: string, the name of the event to get.\n\n        Returns:\n            A list of SnippetEvent, each representing an event from the Java\n            side.\n        \"\"\"\n        raw_events = self._event_client.eventGetAll(self._id, event_name)\n        return [snippet_event.from_dict(msg) for msg in raw_events]\n", "path": "mobly/controllers/android_device_lib/callback_handler.py"}], "after_files": [{"content": "# Copyright 2017 Google Inc.\n# \n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n# \n#     http://www.apache.org/licenses/LICENSE-2.0\n# \n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport time\n\nfrom mobly.controllers.android_device_lib import snippet_event\n\n# The max timeout cannot be larger than the max time the socket waits for a\n# response message. Otherwise, the socket would timeout before the Rpc call\n# does, leaving both server and client in unknown states.\nMAX_TIMEOUT = 60 * 10\nDEFAULT_TIMEOUT = 120  # two minutes\n\n\nclass Error(Exception):\n    pass\n\n\nclass TimeoutError(Error):\n    pass\n\n\nclass CallbackHandler(object):\n    \"\"\"The class used to handle a specific group of callback events.\n\n    All the events handled by a CallbackHandler are originally triggered by one\n    async Rpc call. All the events are tagged with a callback_id specific to a\n    call to an AsyncRpc method defined on the server side.\n\n    The raw message representing an event looks like:\n    {\n        'callbackId': <string, callbackId>,\n        'name': <string, name of the event>,\n        'time': <long, epoch time of when the event was created on the server\n                 side>,\n        'data': <dict, extra data from the callback on the server side>\n    }\n\n    Each message is then used to create a SnippetEvent object on the client\n    side.\n\n    Attributes:\n        ret_value: The direct return value of the async Rpc call.\n    \"\"\"\n\n    def __init__(self, callback_id, event_client, ret_value, method_name):\n        self._id = callback_id\n        self._event_client = event_client\n        self.ret_value = ret_value\n        self._method_name = method_name\n\n    def waitAndGet(self, event_name, timeout=DEFAULT_TIMEOUT):\n        \"\"\"Blocks until an event of the specified name has been received and\n        return the event, or timeout.\n\n        Args:\n            event_name: string, name of the event to get.\n            timeout: float, the number of seconds to wait before giving up.\n\n        Returns:\n            SnippetEvent, the oldest entry of the specified event.\n\n        Raises:\n            Error: If the specified timeout is longer than the max timeout\n                   supported.\n            TimeoutError: The expected event does not occur within time limit.\n        \"\"\"\n        if timeout:\n            if timeout > MAX_TIMEOUT:\n                raise Error(\n                    'Specified timeout %s is longer than max timeout %s.' %\n                    (timeout, MAX_TIMEOUT))\n            timeout *= 1000  # convert to milliseconds for java side\n        try:\n            raw_event = self._event_client.eventWaitAndGet(\n                self._id, event_name, timeout)\n        except Exception as e:\n            if 'EventSnippetException: timeout.' in str(e):\n                raise TimeoutError(\n                    'Timed out after waiting %ss for event \"%s\" triggered by'\n                    ' %s (%s).' % (timeout, event_name, self._method_name,\n                                   self._id))\n            raise\n        return snippet_event.from_dict(raw_event)\n\n    def waitForEvent(self, event_name, predicate, timeout=DEFAULT_TIMEOUT):\n        \"\"\"Wait for an event of a specific name that satisfies the predicate.\n\n        This call will block until the expected event has been received or time\n        out.\n\n        The predicate function defines the condition the event is expected to\n        satisfy. It takes an event and returns True if the condition is\n        satisfied, False otherwise.\n\n        Note all events of the same name that are received but don't satisfy\n        the predicate will be discarded and not be available for further\n        consumption.\n\n        Args:\n          event_name: string, the name of the event to wait for.\n          predicate: function, a function that takes an event (dictionary) and\n                     returns a bool.\n          timeout: float, default is 120s.\n\n        Returns:\n          dictionary, the event that satisfies the predicate if received.\n\n        Raises:\n          TimeoutError: raised if no event that satisfies the predicate is\n                        received after timeout seconds.\n        \"\"\"\n        deadline = time.time() + timeout\n        while time.time() <= deadline:\n            # Calculate the max timeout for the next event rpc call.\n            rpc_timeout = deadline - time.time()\n            if rpc_timeout < 0:\n                break\n            try:\n                event = self.waitAndGet(event_name, rpc_timeout)\n            except TimeoutError:\n                # Ignoring TimeoutError since we need to throw one with a more\n                # specific message.\n                break\n            if predicate(event):\n                return event\n        raise TimeoutError(\n            'Timed out after %ss waiting for an \"%s\" event that satisfies the '\n            'predicate \"%s\".' % (timeout, event_name, predicate.__name__))\n\n    def getAll(self, event_name):\n        \"\"\"Gets all the events of a certain name that have been received so\n        far. This is a non-blocking call.\n\n        Args:\n            callback_id: The id of the callback.\n            event_name: string, the name of the event to get.\n\n        Returns:\n            A list of SnippetEvent, each representing an event from the Java\n            side.\n        \"\"\"\n        raw_events = self._event_client.eventGetAll(self._id, event_name)\n        return [snippet_event.from_dict(msg) for msg in raw_events]\n", "path": "mobly/controllers/android_device_lib/callback_handler.py"}]}