1# 2# Copyright (C) 2016 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16 17import json 18import logging 19import os 20import socket 21import time 22 23from vts.proto import AndroidSystemControlMessage_pb2 as SysMsg_pb2 24from vts.proto import ComponentSpecificationMessage_pb2 as CompSpecMsg_pb2 25from vts.proto import VtsResourceControllerMessage_pb2 as ResControlMsg_pb2 26from vts.runners.host import const 27from vts.runners.host import errors 28from vts.utils.python.mirror import mirror_object 29 30from google.protobuf import text_format 31 32TARGET_IP = os.environ.get("TARGET_IP", None) 33TARGET_PORT = os.environ.get("TARGET_PORT", None) 34_DEFAULT_SOCKET_TIMEOUT_SECS = 1800 35_SOCKET_CONN_TIMEOUT_SECS = 60 36_SOCKET_CONN_RETRY_NUMBER = 5 37COMMAND_TYPE_NAME = { 38 1: "LIST_HALS", 39 2: "SET_HOST_INFO", 40 101: "CHECK_DRIVER_SERVICE", 41 102: "LAUNCH_DRIVER_SERVICE", 42 103: "VTS_AGENT_COMMAND_READ_SPECIFICATION", 43 201: "LIST_APIS", 44 202: "CALL_API", 45 203: "VTS_AGENT_COMMAND_GET_ATTRIBUTE", 46 301: "VTS_AGENT_COMMAND_EXECUTE_SHELL_COMMAND", 47 401: "VTS_FMQ_COMMAND", 48 402: "VTS_HIDL_MEMORY_COMMAND", 49 403: "VTS_HIDL_HANDLE_COMMAND" 50} 51 52 53class VtsTcpClient(object): 54 """VTS TCP Client class. 55 56 Attribute: 57 NO_RESPONSE_MSG: string, error message when there is no response 58 from device. 59 FAIL_RESPONSE_MSG: string, error message when the device sends back 60 a failure message. 61 connection: a TCP socket instance. 62 channel: a file to write and read data. 63 error: string, ongoing tcp connection error. None means no error. 64 _mode: the connection mode (adb_forwarding or ssh_tunnel) 65 timeout: tcp connection timeout. 66 """ 67 68 NO_RESPONSE_MSG = "Framework error: TCP client did not receive response from device." 69 FAIL_RESPONSE_MSG = "Framework error: TCP client received unsuccessful response code." 70 71 def __init__(self, 72 mode="adb_forwarding", 73 timeout=_DEFAULT_SOCKET_TIMEOUT_SECS): 74 self.connection = None 75 self.channel = None 76 self._mode = mode 77 self.timeout = timeout 78 self.error = None 79 80 @property 81 def timeout(self): 82 """Get TCP connection timeout. 83 84 This function assumes timeout property setter is in __init__before 85 any getter calls. 86 87 Returns: 88 int, timeout 89 """ 90 return self._timeout 91 92 @timeout.setter 93 def timeout(self, timeout): 94 """Set TCP connection timeout. 95 96 Args: 97 timeout: int, TCP connection timeout in seconds. 98 """ 99 self._timeout = timeout 100 101 def Heal(self): 102 """Performs a self healing. 103 104 Includes self diagnosis that looks for any framework errors. 105 106 Returns: 107 bool, True if everything is ok; False otherwise. 108 """ 109 res = self.error is None 110 111 if not res: 112 logging.error('Self diagnosis found problems in TCP client: %s', self.error) 113 114 return res 115 116 def Connect(self, 117 ip=TARGET_IP, 118 command_port=TARGET_PORT, 119 callback_port=None, 120 retry=_SOCKET_CONN_RETRY_NUMBER, 121 timeout=None): 122 """Connects to a target device. 123 124 Args: 125 ip: string, the IP address of a target device. 126 command_port: int, the TCP port which can be used to connect to 127 a target device. 128 callback_port: int, the TCP port number of a host-side callback 129 server. 130 retry: int, the number of times to retry connecting before giving 131 up. 132 timeout: tcp connection timeout. 133 134 Returns: 135 True if success, False otherwise 136 137 Raises: 138 socket.error when the connection fails. 139 """ 140 if not command_port: 141 logging.error("ip %s, command_port %s, callback_port %s invalid", 142 ip, command_port, callback_port) 143 return False 144 145 for i in xrange(retry): 146 connection_timeout = self._timeout if timeout is None else timeout 147 try: 148 self.connection = socket.create_connection( 149 (ip, command_port), timeout=connection_timeout) 150 break 151 except socket.error as e: 152 # Wait a bit and retry. 153 logging.exception("Connect failed %s", e) 154 time.sleep(1) 155 if i + 1 == retry: 156 raise errors.VtsTcpClientCreationError( 157 "Couldn't connect to %s:%s" % (ip, command_port)) 158 self.channel = self.connection.makefile(mode="brw") 159 160 if callback_port is not None: 161 self.SendCommand( 162 SysMsg_pb2.SET_HOST_INFO, callback_port=callback_port) 163 resp = self.RecvResponse() 164 if (resp.response_code != SysMsg_pb2.SUCCESS): 165 return False 166 return True 167 168 def Disconnect(self): 169 """Disconnects from the target device. 170 171 TODO(yim): Send a msg to the target side to teardown handler session 172 and release memory before closing the socket. 173 """ 174 if self.connection is not None: 175 self.channel = None 176 self.connection.close() 177 self.connection = None 178 179 def ListHals(self, base_paths): 180 """RPC to LIST_HALS.""" 181 self.SendCommand(SysMsg_pb2.LIST_HALS, paths=base_paths) 182 resp = self.RecvResponse() 183 if (resp.response_code == SysMsg_pb2.SUCCESS): 184 return resp.file_names 185 return None 186 187 def CheckDriverService(self, service_name): 188 """RPC to CHECK_DRIVER_SERVICE.""" 189 self.SendCommand( 190 SysMsg_pb2.CHECK_DRIVER_SERVICE, service_name=service_name) 191 resp = self.RecvResponse() 192 return (resp.response_code == SysMsg_pb2.SUCCESS) 193 194 def LaunchDriverService(self, 195 driver_type, 196 service_name, 197 bits, 198 file_path=None, 199 target_class=None, 200 target_type=None, 201 target_version_major=None, 202 target_version_minor=None, 203 target_package=None, 204 target_component_name=None, 205 hw_binder_service_name=None, 206 is_test_hal=None): 207 """RPC to LAUNCH_DRIVER_SERVICE. 208 209 Args: 210 driver_type: enum, type of the driver (shared lib, shell). 211 service_name: string, binder service name. 212 bits: int, whether a target driver binary is 64-bits or 32-bits. 213 file_path: string, the name of a target. 214 target_class: int, target class. 215 target_type: int, target type. 216 target_version_major: int, HAL major version, e.g. 1.0 -> 1. 217 target_version_minor: int, HAL minor version, e.g. 1.0 -> 0. 218 target_package: string, package name of a HIDL HAL. 219 target_component_name: string, name of a target component. 220 hw_binder_service_name: name of a HW Binder service to use. 221 is_test_hal: bool, whether the HAL service is a test HAL 222 (e.g. msgq). 223 224 Returns: 225 response code, -1 or 0 on failure, other values on success. 226 """ 227 logging.debug("service_name: %s", service_name) 228 logging.debug("file_path: %s", file_path) 229 logging.debug("bits: %s", bits) 230 logging.debug("driver_type: %s", driver_type) 231 self.SendCommand( 232 SysMsg_pb2.LAUNCH_DRIVER_SERVICE, 233 driver_type=driver_type, 234 service_name=service_name, 235 bits=bits, 236 file_path=file_path, 237 target_class=target_class, 238 target_type=target_type, 239 target_version_major=target_version_major, 240 target_version_minor=target_version_minor, 241 target_package=target_package, 242 target_component_name=target_component_name, 243 hw_binder_service_name=hw_binder_service_name, 244 is_test_hal=is_test_hal) 245 resp = self.RecvResponse() 246 logging.debug("resp for LAUNCH_DRIVER_SERVICE: %s", resp) 247 if driver_type == SysMsg_pb2.VTS_DRIVER_TYPE_HAL_HIDL \ 248 or driver_type == SysMsg_pb2.VTS_DRIVER_TYPE_HAL_CONVENTIONAL \ 249 or driver_type == SysMsg_pb2.VTS_DRIVER_TYPE_HAL_LEGACY: 250 if resp.response_code == SysMsg_pb2.SUCCESS: 251 return int(resp.result) 252 else: 253 return -1 254 else: 255 return (resp.response_code == SysMsg_pb2.SUCCESS) 256 257 def ListApis(self): 258 """RPC to LIST_APIS.""" 259 self.SendCommand(SysMsg_pb2.LIST_APIS) 260 resp = self.RecvResponse() 261 logging.debug("resp for LIST_APIS: %s", resp) 262 if (resp.response_code == SysMsg_pb2.SUCCESS): 263 return resp.spec 264 return None 265 266 def GetPythonDataOfVariableSpecMsg(self, var_spec_msg): 267 """Returns the python native data structure for a given message. 268 269 Args: 270 var_spec_msg: VariableSpecificationMessage 271 272 Returns: 273 python native data structure (e.g., string, integer, list). 274 275 Raises: 276 VtsUnsupportedTypeError if unsupported type is specified. 277 VtsMalformedProtoStringError if StringDataValueMessage is 278 not populated. 279 """ 280 if var_spec_msg.type == CompSpecMsg_pb2.TYPE_SCALAR: 281 scalar_type = getattr(var_spec_msg, "scalar_type", "") 282 if scalar_type: 283 return getattr(var_spec_msg.scalar_value, scalar_type) 284 elif var_spec_msg.type == CompSpecMsg_pb2.TYPE_ENUM: 285 scalar_type = getattr(var_spec_msg, "scalar_type", "") 286 if scalar_type: 287 return getattr(var_spec_msg.scalar_value, scalar_type) 288 else: 289 return var_spec_msg.scalar_value.int32_t 290 elif var_spec_msg.type == CompSpecMsg_pb2.TYPE_STRING: 291 if hasattr(var_spec_msg, "string_value"): 292 return getattr(var_spec_msg.string_value, "message", "") 293 raise errors.VtsMalformedProtoStringError() 294 elif var_spec_msg.type == CompSpecMsg_pb2.TYPE_STRUCT: 295 result = {} 296 index = 1 297 for struct_value in var_spec_msg.struct_value: 298 if len(struct_value.name) > 0: 299 result[struct_value. 300 name] = self.GetPythonDataOfVariableSpecMsg( 301 struct_value) 302 else: 303 result["attribute%d" % 304 index] = self.GetPythonDataOfVariableSpecMsg( 305 struct_value) 306 index += 1 307 return result 308 elif var_spec_msg.type == CompSpecMsg_pb2.TYPE_UNION: 309 result = {} 310 index = 1 311 for union_value in var_spec_msg.union_value: 312 if len(union_value.name) > 0: 313 result[union_value. 314 name] = self.GetPythonDataOfVariableSpecMsg( 315 union_value) 316 else: 317 result["attribute%d" % 318 index] = self.GetPythonDataOfVariableSpecMsg( 319 union_value) 320 index += 1 321 return result 322 elif (var_spec_msg.type == CompSpecMsg_pb2.TYPE_VECTOR 323 or var_spec_msg.type == CompSpecMsg_pb2.TYPE_ARRAY): 324 result = [] 325 for vector_value in var_spec_msg.vector_value: 326 result.append( 327 self.GetPythonDataOfVariableSpecMsg(vector_value)) 328 return result 329 elif (var_spec_msg.type == CompSpecMsg_pb2.TYPE_HIDL_INTERFACE 330 or var_spec_msg.type == CompSpecMsg_pb2.TYPE_FMQ_SYNC 331 or var_spec_msg.type == CompSpecMsg_pb2.TYPE_FMQ_UNSYNC 332 or var_spec_msg.type == CompSpecMsg_pb2.TYPE_HIDL_MEMORY 333 or var_spec_msg.type == CompSpecMsg_pb2.TYPE_HANDLE): 334 logging.debug("var_spec_msg: %s", var_spec_msg) 335 return var_spec_msg 336 337 raise errors.VtsUnsupportedTypeError( 338 "unsupported type %s" % var_spec_msg.type) 339 340 def CallApi(self, arg, caller_uid=None): 341 """RPC to CALL_API.""" 342 self.SendCommand(SysMsg_pb2.CALL_API, arg=arg, caller_uid=caller_uid) 343 resp = self.RecvResponse() 344 resp_code = resp.response_code 345 if (resp_code == SysMsg_pb2.SUCCESS): 346 result = CompSpecMsg_pb2.FunctionSpecificationMessage() 347 if resp.result == "error": 348 raise errors.VtsTcpCommunicationError( 349 "API call error by the VTS driver.") 350 try: 351 text_format.Merge(resp.result, result) 352 except text_format.ParseError as e: 353 logging.exception(e) 354 logging.error("Paring error\n%s", resp.result) 355 if result.return_type.type == CompSpecMsg_pb2.TYPE_SUBMODULE: 356 logging.debug("returned a submodule spec") 357 logging.debug("spec: %s", result.return_type_submodule_spec) 358 return mirror_object.MirrorObject( 359 self, result.return_type_submodule_spec, None) 360 361 if result.HasField("return_type"): # For non-HIDL return value 362 result_value = result 363 else: 364 result_value = [] 365 for return_type_hidl in result.return_type_hidl: 366 result_value.append( 367 self.GetPythonDataOfVariableSpecMsg(return_type_hidl)) 368 369 if len(result.raw_coverage_data) > 0: 370 return result_value, {"coverage": result.raw_coverage_data} 371 else: 372 return result_value 373 374 logging.error("NOTICE - Likely a crash discovery!") 375 logging.error("SysMsg_pb2.SUCCESS is %s", SysMsg_pb2.SUCCESS) 376 raise errors.VtsTcpCommunicationError( 377 "RPC Error, response code for %s is %s" % (arg, resp_code)) 378 379 def GetAttribute(self, arg): 380 """RPC to VTS_AGENT_COMMAND_GET_ATTRIBUTE.""" 381 self.SendCommand(SysMsg_pb2.VTS_AGENT_COMMAND_GET_ATTRIBUTE, arg=arg) 382 resp = self.RecvResponse() 383 resp_code = resp.response_code 384 if (resp_code == SysMsg_pb2.SUCCESS): 385 result = CompSpecMsg_pb2.FunctionSpecificationMessage() 386 if resp.result == "error": 387 raise errors.VtsTcpCommunicationError( 388 "Get attribute request failed on target.") 389 try: 390 text_format.Merge(resp.result, result) 391 except text_format.ParseError as e: 392 logging.exception(e) 393 logging.error("Paring error\n%s", resp.result) 394 if result.return_type.type == CompSpecMsg_pb2.TYPE_SUBMODULE: 395 logging.debug("returned a submodule spec") 396 logging.debug("spec: %s", result.return_type_submodule_spec) 397 return mirror_object.MirrorObject( 398 self, result.return_type_submodule_spec, None) 399 elif result.return_type.type == CompSpecMsg_pb2.TYPE_SCALAR: 400 return getattr(result.return_type.scalar_value, 401 result.return_type.scalar_type) 402 return result 403 logging.error("NOTICE - Likely a crash discovery!") 404 logging.error("SysMsg_pb2.SUCCESS is %s", SysMsg_pb2.SUCCESS) 405 raise errors.VtsTcpCommunicationError( 406 "RPC Error, response code for %s is %s" % (arg, resp_code)) 407 408 def ExecuteShellCommand(self, command, no_except=False): 409 """RPC to VTS_AGENT_COMMAND_EXECUTE_SHELL_COMMAND. 410 411 Args: 412 command: string or list or tuple, command to execute on device 413 no_except: bool, whether to throw exceptions. If set to True, 414 when exception happens, return code will be -1 and 415 str(err) will be in stderr. Result will maintain the 416 same length as with input command. 417 418 Returns: 419 dictionary of list, command results that contains stdout, 420 stderr, and exit_code. 421 """ 422 try: 423 return self.__ExecuteShellCommand(command) 424 except Exception as e: 425 self.error = e 426 if not no_except: 427 raise e 428 logging.exception(e) 429 return { 430 const.STDOUT: [""] * len(command), 431 const.STDERR: [str(e)] * len(command), 432 const.EXIT_CODE: [-1] * len(command) 433 } 434 435 def __ExecuteShellCommand(self, command): 436 """RPC to VTS_AGENT_COMMAND_EXECUTE_SHELL_COMMAND. 437 438 Args: 439 command: string or list of string, command to execute on device 440 441 Returns: 442 dictionary of list, command results that contains stdout, 443 stderr, and exit_code. 444 """ 445 self.SendCommand( 446 SysMsg_pb2.VTS_AGENT_COMMAND_EXECUTE_SHELL_COMMAND, 447 shell_command=command) 448 resp = self.RecvResponse(retries=2) 449 logging.debug("resp for VTS_AGENT_COMMAND_EXECUTE_SHELL_COMMAND: %s", 450 resp) 451 452 stdout = [] 453 stderr = [] 454 exit_code = -1 455 456 if not resp: 457 logging.error(self.NO_RESPONSE_MSG) 458 stderr = [self.NO_RESPONSE_MSG] 459 self.error = self.NO_RESPONSE_MSG 460 elif resp.response_code != SysMsg_pb2.SUCCESS: 461 logging.error(self.FAIL_RESPONSE_MSG) 462 stderr = [self.FAIL_RESPONSE_MSG] 463 self.error = self.FAIL_RESPONSE_MSG 464 else: 465 stdout = resp.stdout 466 stderr = resp.stderr 467 exit_code = resp.exit_code 468 self.error = None 469 470 return { 471 const.STDOUT: stdout, 472 const.STDERR: stderr, 473 const.EXIT_CODE: exit_code 474 } 475 476 def SendFmqRequest(self, message): 477 """Sends a command to the FMQ driver and receives the response. 478 479 Args: 480 message: FmqRequestMessage, message that contains the arguments 481 in the FMQ request. 482 483 Returns: 484 FmqResponseMessage, which includes all possible return value types, 485 including int, bool, and data read from the queue. 486 """ 487 self.SendCommand(SysMsg_pb2.VTS_FMQ_COMMAND, fmq_request=message) 488 resp = self.RecvResponse() 489 logging.debug("resp for VTS_FMQ_COMMAND: %s", resp) 490 return self.CheckResourceCommandResponse( 491 resp, getattr(resp, "fmq_response", None)) 492 493 def SendHidlMemoryRequest(self, message): 494 """Sends a command to the hidl_memory driver and receives the response. 495 496 Args: 497 message: HidlMemoryRequestMessage, message that contains the arguments 498 in the hidl_memory request. 499 500 Returns: 501 HidlMemoryResponseMessage, return values needed by the host-side caller. 502 """ 503 self.SendCommand( 504 SysMsg_pb2.VTS_HIDL_MEMORY_COMMAND, hidl_memory_request=message) 505 resp = self.RecvResponse() 506 logging.debug("resp for VTS_HIDL_MEMORY_COMMAND: %s", resp) 507 return self.CheckResourceCommandResponse( 508 resp, getattr(resp, "hidl_memory_response", None)) 509 510 def SendHidlHandleRequest(self, message): 511 """Sends a command to the hidl_handle driver and receives the response. 512 513 Args: 514 message: HidlHandleRequestMessage, message that contains the arguments 515 in the hidl_handle request. 516 517 Returns: 518 HidlHandleResponseMessage, return values needed by the host-side caller. 519 """ 520 self.SendCommand( 521 SysMsg_pb2.VTS_HIDL_HANDLE_COMMAND, hidl_handle_request=message) 522 resp = self.RecvResponse() 523 logging.debug("resp for VTS_HIDL_HANDLE_COMMAND: %s", resp) 524 return self.CheckResourceCommandResponse( 525 resp, getattr(resp, "hidl_handle_response", None)) 526 527 @staticmethod 528 def CheckResourceCommandResponse(agent_response, resource_response): 529 """Checks the response from a VTS resource command. 530 531 This function checks and logs framework errors such as not receiving 532 a response, receving a failure response. Then it checks the response 533 for the resource type is not None, and logs error if needed. 534 535 Args: 536 agent_response: AndroidSystemControlResponseMessage, 537 response from agent. 538 resource_response: FmqResponseMessage, HidlMemoryResponseMessage, 539 or HidlHandleResponseMessage, the response for 540 one of fmq, hidl_memory, and hidl_handle. 541 542 Returns: 543 resource_response that is passed in. 544 """ 545 if agent_response is None: 546 logging.error(VtsTcpClient.NO_RESPONSE_MSG) 547 elif agent_response.response_code != SysMsg_pb2.SUCCESS: 548 logging.error(VtsTcpClient.FAIL_RESPONSE_MSG) 549 elif resource_response is None: 550 logging.error("TCP client did not receive a response for " + 551 "the resource command.") 552 return resource_response 553 554 def Ping(self): 555 """RPC to send a PING request. 556 557 Returns: 558 True if the agent is alive, False otherwise. 559 """ 560 self.SendCommand(SysMsg_pb2.PING) 561 resp = self.RecvResponse() 562 logging.debug("resp for PING: %s", resp) 563 if resp is not None and resp.response_code == SysMsg_pb2.SUCCESS: 564 return True 565 return False 566 567 def ReadSpecification(self, 568 interface_name, 569 target_class, 570 target_type, 571 target_version_major, 572 target_version_minor, 573 target_package, 574 recursive=False): 575 """RPC to VTS_AGENT_COMMAND_READ_SPECIFICATION. 576 577 Args: 578 other args: see SendCommand 579 recursive: boolean, set to recursively read the imported 580 specification(s) and return the merged one. 581 """ 582 self.SendCommand( 583 SysMsg_pb2.VTS_AGENT_COMMAND_READ_SPECIFICATION, 584 service_name=interface_name, 585 target_class=target_class, 586 target_type=target_type, 587 target_version_major=target_version_major, 588 target_version_minor=target_version_minor, 589 target_package=target_package) 590 resp = self.RecvResponse(retries=2) 591 logging.debug("resp for VTS_AGENT_COMMAND_EXECUTE_READ_INTERFACE: %s", 592 resp) 593 logging.debug("proto: %s", resp.result) 594 result = CompSpecMsg_pb2.ComponentSpecificationMessage() 595 if resp.result == "error": 596 raise errors.VtsTcpCommunicationError( 597 "API call error by the VTS driver.") 598 try: 599 text_format.Merge(resp.result, result) 600 except text_format.ParseError as e: 601 logging.exception(e) 602 logging.error("Paring error\n%s", resp.result) 603 604 if recursive and hasattr(result, "import"): 605 for imported_interface in getattr(result, "import"): 606 if imported_interface == "android.hidl.base@1.0::types": 607 logging.warn("import android.hidl.base@1.0::types skipped") 608 continue 609 [package, version_str] = imported_interface.split("@") 610 [version_major, 611 version_minor] = (version_str.split("::")[0]).split(".") 612 imported_result = self.ReadSpecification( 613 imported_interface.split("::")[1], 614 # TODO(yim): derive target_class and 615 # target_type from package path or remove them 616 msg.component_class 617 if target_class is None else target_class, 618 msg.component_type if target_type is None else target_type, 619 int(version_major), 620 int(version_minor), 621 package) 622 # Merge the attributes from imported interface. 623 for attribute in imported_result.attribute: 624 imported_attribute = result.attribute.add() 625 imported_attribute.CopyFrom(attribute) 626 627 return result 628 629 def SendCommand(self, 630 command_type, 631 paths=None, 632 file_path=None, 633 bits=None, 634 target_class=None, 635 target_type=None, 636 target_version_major=None, 637 target_version_minor=None, 638 target_package=None, 639 target_component_name=None, 640 hw_binder_service_name=None, 641 is_test_hal=None, 642 module_name=None, 643 service_name=None, 644 callback_port=None, 645 driver_type=None, 646 shell_command=None, 647 caller_uid=None, 648 arg=None, 649 fmq_request=None, 650 hidl_memory_request=None, 651 hidl_handle_request=None): 652 """Sends a command. 653 654 Args: 655 command_type: integer, the command type. 656 each of the other args are to fill in a field in 657 AndroidSystemControlCommandMessage. 658 """ 659 if not self.channel: 660 raise errors.VtsTcpCommunicationError( 661 "channel is None, unable to send command.") 662 663 command_msg = SysMsg_pb2.AndroidSystemControlCommandMessage() 664 command_msg.command_type = command_type 665 logging.debug("sending a command (type %s)", 666 COMMAND_TYPE_NAME[command_type]) 667 if command_type == 202: 668 logging.debug("target API: %s", arg) 669 670 if target_class is not None: 671 command_msg.target_class = target_class 672 673 if target_type is not None: 674 command_msg.target_type = target_type 675 676 if target_version_major is not None: 677 command_msg.target_version_major = target_version_major 678 679 if target_version_minor is not None: 680 command_msg.target_version_minor = target_version_minor 681 682 if target_package is not None: 683 command_msg.target_package = target_package 684 685 if target_component_name is not None: 686 command_msg.target_component_name = target_component_name 687 688 if hw_binder_service_name is not None: 689 command_msg.hw_binder_service_name = hw_binder_service_name 690 691 if is_test_hal is not None: 692 command_msg.is_test_hal = is_test_hal 693 694 if module_name is not None: 695 command_msg.module_name = module_name 696 697 if service_name is not None: 698 command_msg.service_name = service_name 699 700 if driver_type is not None: 701 command_msg.driver_type = driver_type 702 703 if paths is not None: 704 command_msg.paths.extend(paths) 705 706 if file_path is not None: 707 command_msg.file_path = file_path 708 709 if bits is not None: 710 command_msg.bits = bits 711 712 if callback_port is not None: 713 command_msg.callback_port = callback_port 714 715 if caller_uid is not None: 716 command_msg.driver_caller_uid = caller_uid 717 718 if arg is not None: 719 command_msg.arg = arg 720 721 if shell_command is not None: 722 if isinstance(shell_command, (list, tuple)): 723 command_msg.shell_command.extend(shell_command) 724 else: 725 command_msg.shell_command.append(shell_command) 726 727 if fmq_request is not None: 728 command_msg.fmq_request.CopyFrom(fmq_request) 729 730 if hidl_memory_request is not None: 731 command_msg.hidl_memory_request.CopyFrom(hidl_memory_request) 732 733 if hidl_handle_request is not None: 734 command_msg.hidl_handle_request.CopyFrom(hidl_handle_request) 735 736 logging.debug("command %s" % command_msg) 737 message = command_msg.SerializeToString() 738 message_len = len(message) 739 logging.debug("sending %d bytes", message_len) 740 self.channel.write(str(message_len) + b'\n') 741 self.channel.write(message) 742 self.channel.flush() 743 744 def RecvResponse(self, retries=0): 745 """Receives and parses the response, and returns the relevant ResponseMessage. 746 747 Args: 748 retries: an integer indicating the max number of retries in case of 749 session timeout error. 750 """ 751 for index in xrange(1 + retries): 752 try: 753 if index != 0: 754 logging.info("retrying...") 755 header = self.channel.readline().strip("\n") 756 length = int(header) if header else 0 757 logging.debug("resp %d bytes", length) 758 data = self.channel.read(length) 759 response_msg = SysMsg_pb2.AndroidSystemControlResponseMessage() 760 response_msg.ParseFromString(data) 761 logging.debug( 762 "Response %s", "success" 763 if response_msg.response_code == SysMsg_pb2.SUCCESS else 764 "fail") 765 return response_msg 766 except socket.timeout as e: 767 logging.exception(e) 768 return None 769