Home | History | Annotate | Download | only in controllers
      1 #!/usr/bin/env python3.4
      2 #
      3 #   Copyright 2016 - The Android Open Source Project
      4 #
      5 #   Licensed under the Apache License, Version 2.0 (the "License");
      6 #   you may not use this file except in compliance with the License.
      7 #   You may obtain a copy of 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,
     13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 #   See the License for the specific language governing permissions and
     15 #   limitations under the License.
     16 
     17 from acts.controllers.android_device import AndroidDevice
     18 from acts.controllers.utils_lib import host_utils
     19 import acts.controllers.native as native
     20 from subprocess import call
     21 
     22 import logging
     23 import time
     24 
     25 #TODO(tturney): Merge this into android device
     26 
     27 ACTS_CONTROLLER_CONFIG_NAME = "NativeAndroidDevice"
     28 ACTS_CONTROLLER_REFERENCE_NAME = "native_android_devices"
     29 
     30 
     31 def create(configs):
     32     logger = logging
     33     ads = get_instances(configs)
     34     for ad in ads:
     35         try:
     36             ad.get_droid()
     37         except:
     38             logger.exception("Failed to start sl4n on %s" % ad.serial)
     39     return ads
     40 
     41 
     42 def destroy(ads):
     43     pass
     44 
     45 
     46 def get_instances(serials, ):
     47     """Create AndroidDevice instances from a list of serials.
     48 
     49     Args:
     50         serials: A list of android device serials.
     51         logger: A logger to be passed to each instance.
     52 
     53     Returns:
     54         A list of AndroidDevice objects.
     55     """
     56     results = []
     57     for s in serials:
     58         results.append(NativeAndroidDevice(s))
     59     return results
     60 
     61 
     62 class NativeAndroidDeviceError(Exception):
     63     pass
     64 
     65 
     66 class NativeAndroidDevice(AndroidDevice):
     67     def __del__(self):
     68         if self.h_port:
     69             self.adb.forward("--remove tcp:%d" % self.h_port)
     70 
     71     def get_droid(self, handle_event=True):
     72         """Create an sl4n connection to the device.
     73 
     74         Return the connection handler 'droid'. By default, another connection
     75         on the same session is made for EventDispatcher, and the dispatcher is
     76         returned to the caller as well.
     77         If sl4n server is not started on the device, try to start it.
     78 
     79         Args:
     80             handle_event: True if this droid session will need to handle
     81                 events.
     82 
     83         Returns:
     84             droid: Android object useds to communicate with sl4n on the android
     85                 device.
     86             ed: An optional EventDispatcher to organize events for this droid.
     87 
     88         Examples:
     89             Don't need event handling:
     90             >>> ad = NativeAndroidDevice()
     91             >>> droid = ad.get_droid(False)
     92 
     93             Need event handling:
     94             >>> ad = NativeAndroidDevice()
     95             >>> droid, ed = ad.get_droid()
     96         """
     97         if not self.h_port or not host_utils.is_port_available(self.h_port):
     98             self.h_port = host_utils.get_available_host_port()
     99         self.adb.tcp_forward(self.h_port, self.d_port)
    100         pid = self.adb.shell("pidof -s sl4n", ignore_status=True)
    101         while (pid):
    102             self.adb.shell("kill {}".format(pid))
    103             pid = self.adb.shell("pidof -s sl4n", ignore_status=True)
    104         call(
    105             ["adb -s " + self.serial + " shell sh -c \"/system/bin/sl4n\" &"],
    106             shell=True)
    107         try:
    108             time.sleep(3)
    109             droid = self.start_new_session()
    110         except:
    111             droid = self.start_new_session()
    112         return droid
    113 
    114     def start_new_session(self):
    115         """Start a new session in sl4n.
    116 
    117         Also caches the droid in a dict with its uid being the key.
    118 
    119         Returns:
    120             An Android object used to communicate with sl4n on the android
    121                 device.
    122 
    123         Raises:
    124             sl4nException: Something is wrong with sl4n and it returned an
    125             existing uid to a new session.
    126         """
    127         droid = native.NativeAndroid(port=self.h_port)
    128         droid.open()
    129         if droid.uid in self._droid_sessions:
    130             raise bt.SL4NException(("SL4N returned an existing uid for a "
    131                                     "new session. Abort."))
    132             return droid
    133         self._droid_sessions[droid.uid] = [droid]
    134         return droid
    135