1#!/usr/bin/env python3
2#
3# Copyright (C) 2009 Google Inc.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may not
6# use this file except in compliance with the License. You may obtain a copy of
7# the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations under
15# the License.
16
17from acts.controllers.sl4a_lib.rpc_connection import RpcConnection
18import json
19import os
20
21HOST = os.environ.get('AP_HOST', None)
22PORT = os.environ.get('AP_PORT', 9999)
23
24
25class SL4NException(Exception):
26    pass
27
28
29class SL4NAPIError(SL4NException):
30    """Raised when remote API reports an error."""
31
32
33class SL4NProtocolError(SL4NException):
34    """Raised when there is an error exchanging data with the device server."""
35    NO_RESPONSE_FROM_HANDSHAKE = "No response from handshake."
36    NO_RESPONSE_FROM_SERVER = "No response from server."
37    MISMATCHED_API_ID = "Mismatched API id."
38
39
40def IDCounter():
41    i = 0
42    while True:
43        yield i
44        i += 1
45
46
47class NativeAndroid(RpcConnection):
48    COUNTER = IDCounter()
49
50    def _rpc(self, method, *args):
51        with self._lock:
52            apiid = next(self._counter)
53        data = {'id': apiid, 'method': method, 'params': args}
54        request = json.dumps(data)
55        self.client.write(request.encode("utf8") + b'\n')
56        self.client.flush()
57        response = self.client.readline()
58        if not response:
59            raise SL4NProtocolError(SL4NProtocolError.NO_RESPONSE_FROM_SERVER)
60        #TODO: (tturney) fix the C side from sending \x00 char over the socket.
61        result = json.loads(
62            str(response, encoding="utf8").rstrip().replace("\x00", ""))
63        if result['error']:
64            raise SL4NAPIError(result['error'])
65        if result['id'] != apiid:
66            raise SL4NProtocolError(SL4NProtocolError.MISMATCHED_API_ID)
67        return result['result']
68