Best Python code snippet using fMBT_python
fmbtandroid.py
Source:fmbtandroid.py  
...1044            rotation = ROTATION_DEGS.index(rotation)1045        else:1046            raise ValueError('invalid rotation "%s"' % (rotation,))1047        if self._conn:1048            return self._conn.sendUserRotation(rotation)1049        else:1050            return False1051    def shell(self, shellCommand, timeout=None):1052        """1053        Execute shellCommand in adb shell.1054        Parameters:1055          shellCommand (string):1056                  command to be executed in adb shell.1057                  Arguments separated by whitespace.1058          timeout (optional, integer):1059                  time in seconds after which the command1060                  will timeout. The default is None (no timeout).1061        Returns output of "adb shell" command, or None if timed out.1062        If you wish to receive exitstatus or standard output and error1063        separated from shellCommand, refer to shellSOE().1064        """1065        try:1066            output = self.existingConnection()._runAdb(1067                ["shell", shellCommand],1068                expectedExitStatus=EXITSTATUS_ANY,1069                timeout=timeout)[1]1070        except FMBTAndroidRunError:1071            output = None1072        return output1073    def shellSOE(self, shellCommand, timeout=None):1074        """1075        Execute shellCommand in adb shell.1076        Parameters:1077          shellCommand (string):1078                  command to be executed in adb shell.1079                  Arguments separated by whitespace.1080          timeout (optional, integer):1081                  time in seconds after which the command1082                  will timeout. The default is None (no timeout).1083        Returns tuple (exitStatus, standardOutput, standardError)1084        or (None, None, None) if timed out.1085        Requires tar and uuencode to be available on the device.1086        """1087        return self.existingConnection().shellSOE(shellCommand, timeout)1088    def smsNumber(self, number, message):1089        """1090        Send message using SMS to given number.1091        Parameters:1092          number (string)1093                  phone number to which the SMS will be sent1094          message (string)1095                  the message to be sent.1096        Returns True on success, otherwise False.1097        """1098        smsCommand = ('am start -a android.intent.action.SENDTO ' +1099                      '-d sms:%s --es sms_body "%s"' +1100                      ' --ez exit_on_sent true')  % (number, message)1101        status, out, err = self.shellSOE(smsCommand)1102        if status != 0:1103            _logFailedCommand("sms", smsCommand, status, out, err)1104            return False1105        _adapterLog("SMS command returned %s" % (out + err,))1106        time.sleep(2)1107        if 'talk' in self.topWindow():1108            _adapterLog("Messaging app is Hangouts")1109            self.pressKey("KEYCODE_ENTER")1110            time.sleep(1)1111            self.pressKey("KEYCODE_BACK")1112            time.sleep(1)1113            self.pressKey("KEYCODE_BACK")1114        else:1115            self.pressKey("KEYCODE_DPAD_RIGHT")1116            time.sleep(1)1117            self.pressKey("KEYCODE_ENTER")1118        return True1119    def statusBarVisible(self):1120        """1121        Returns True if the status bar is showing, otherwise False.1122        """1123        return self.existingConnection().recvStatusBarVisible()1124    def supportsView(self):1125        """1126        Check if connected device supports reading view data.1127        View data is needed by refreshView(), view(), verifyText() and1128        waitText(). It is produced by Android window dump.1129        Returns True if view data can be read, otherwise False.1130        """1131        if self._supportsView == None:1132            try:1133                if self.uiautomatorDump():1134                    if self.existingConnection().recvUiautomatorDump():1135                        self._supportsView = True1136                    else:1137                        self._supportsView = False1138                else:1139                    self.existingConnection().recvViewData()1140                    self._supportsView = True1141            except AndroidConnectionError:1142                self._supportsView = False1143        return self._supportsView1144    def swipeText(self, text, direction, partial=False, **swipeKwArgs):1145        """1146        Find an item with given text from the latest view, and swipe it.1147        Parameters:1148          text (string):1149                  text to be swiped.1150          direction (string or integer):1151                  refer to swipe documentation1152          distance (float, optional):1153                  refer to swipe documentation1154          partial (boolean, optional):1155                  refer to verifyText documentation. The default is1156                  False.1157          startPos1158                  refer to swipeItem documentation.1159          delayBeforeMoves, delayBetweenMoves, delayAfterMoves,1160          movePoints1161                  refer to drag documentation.1162        Returns True if successful, otherwise False.1163        """1164        assert self._lastView != None, "View required."1165        items = self._lastView.findItemsByText(text, partial=partial, count=1, onScreen=True)1166        if len(items) == 0: return False1167        return self.swipeItem(items[0], direction, **swipeKwArgs)1168    def systemProperty(self, propertyName):1169        """1170        Returns Android Monkey Device properties, such as1171        "clock.uptime", refer to Android Monkey documentation.1172        """1173        return self.existingConnection().recvVariable(propertyName)1174    def tapId(self, viewItemId, **tapKwArgs):1175        """1176        Find an item with given id from the latest view, and tap it.1177        """1178        assert self._lastView != None, "View required."1179        items = self._lastView.findItemsById(viewItemId, count=1, onScreen=True)1180        if len(items) > 0:1181            return self.tapItem(items[0], **tapKwArgs)1182        else:1183            _adapterLog("tapItemById(%s): no items found" % (viewItemId,))1184            return False1185    def tapText(self, text, partial=False, **tapKwArgs):1186        """1187        Find an item with given text from the latest view, and tap it.1188        Parameters:1189          partial (boolean, optional):1190                  refer to verifyText documentation. The default is1191                  False.1192          tapPos (pair of floats (x, y), optional):1193                  refer to tapItem documentation.1194          long, hold, count, delayBetweenTaps (optional):1195                  refer to tap documentation.1196        Returns True if successful, otherwise False.1197        """1198        assert self._lastView != None, "View required."1199        items = self._lastView.findItemsByText(text, partial=partial, count=1, onScreen=True)1200        if len(items) == 0: return False1201        return self.tapItem(items[0], **tapKwArgs)1202    def tapContentDesc(self, contentDesc, **tapKwArgs):1203        """1204        Find an item with given content description, and tap it.1205        Parameters:1206          contentDesc (string):1207                  content description of the item to be tapped.1208          tapPos (pair of floats (x, y), optional):1209                  refer to tapItem documentation.1210          long, hold, count, delayBetweenTaps (optional):1211                  refer to tap documentation.1212        Returns True if successful, otherwise False.1213        Note: Requires that the latest refreshView used the uiautomator1214        backend for fetching the view data. Example:1215        d.refreshView(uiautomatorDump=True)1216        d.tapContentDesc("Apps")1217        """1218        assert self._lastView != None, "View required."1219        items = self._lastView.findItemsByContentDesc(contentDesc)1220        if len(items) == 0: return False1221        return self.tapItem(items[0], **tapKwArgs)1222    def topApp(self):1223        """1224        Returns the name of the top application.1225        """1226        if not self._conn:1227            return None1228        else:1229            return self._conn.recvTopAppWindow()[0]1230    def topWindow(self):1231        """1232        Returns the name of the top window.1233        """1234        # the top window may be None during transitions, therefore1235        # retry a couple of times if necessary.1236        if not self._conn:1237            return None1238        timeout = 0.51239        pollDelay = 0.21240        start = time.time()1241        tw = self.existingConnection().recvTopAppWindow()[1]1242        while tw == None and (time.time() - start < timeout):1243            time.sleep(pollDelay)1244            tw = self.existingConnection().recvTopAppWindow()[1]1245        return tw1246    def topWindowStack(self):1247        """1248        Returns window names in the stack of the top fullscreen application.1249        The topmost window is the last one in the list.1250        """1251        return self.existingConnection().recvTopWindowStack()1252    def uiautomatorDump(self):1253        """1254        Returns whether or not uiautomator is used for refreshView()1255        """1256        return self._uiautomatorDump1257    def uninstall(self, apkname, keepData=False):1258        """1259        Uninstall a package from the device.1260        Parameters:1261          package (string):1262                  the package to be uninstalled.1263          keepData (boolean, optional):1264                  keep app data and cache.1265                  Corresponds to adb uninstall "-k".1266                  The default is False.1267        Returns True on success, otherwise False.1268        Example:1269          d.uninstall("com.android.python27")1270        """1271        if self._conn:1272            return self._conn.uninstall(apkname, keepData)1273        else:1274            return False1275    def userRotation(self):1276        """1277        Returns rotation set with setUserRotation.1278        """1279        return self.existingConnection().recvUserRotation()1280    def verifyText(self, text, partial=False):1281        """1282        Verify that the last view has at least one item with given1283        text.1284        Parameters:1285          text (string):1286                  text to be searched for in items.1287          partial (boolean, optional):1288                  if True, match items if item text contains given1289                  text, otherwise match only if item text is equal to1290                  the given text. The default is False (exact match).1291        """1292        assert self._lastView != None, "View required."1293        return self._lastView.findItemsByText(text, partial=partial, count=1, onScreen=True) != []1294    def view(self):1295        """1296        Returns the last view (the most recently refreshed view).1297        """1298        return self._lastView1299    def waitAnyText(self, listOfTexts, partial=False, uiautomatorDump=False, **waitKwArgs):1300        """1301        Wait until any of texts is on the screen.1302        Parameters:1303          listOfTexts (list of string):1304                  texts to be waited for.1305          partial (boolean, optional):1306                refer to verifyText. The default is False.1307          uiautomatorDump (boolean, optional):1308                use uiautomator to read view dump from the device.1309                If not given, uiautomatorDump() default will be used.1310          waitTime, pollDelay, beforeRefresh, afterRefresh (optional):1311                  refer to wait documentation.1312        Returns list of texts that appear in the first refreshed view1313        that contains at least one of the texts. If none of the texts1314        appear within the time limit, returns empty list.1315        If any of texts is not found from the latest refreshed1316        view, waitAnyText will update the view in pollDelay interval until1317        waitTime is exceeded.1318        """1319        if listOfTexts == []: return []1320        if not self._lastView: self.refreshView(uiautomatorDump=uiautomatorDump)1321        waitArgs, rest = fmbtgti._takeWaitArgs(waitKwArgs)1322        foundTexts = []1323        def observe():1324            for text in listOfTexts:1325                if self.verifyText(text, partial=partial):1326                    foundTexts.append(text)1327            return foundTexts != []1328        self.wait(1329            lambda: self.refreshView(uiautomatorDump=uiautomatorDump),1330            observe, **waitArgs)1331        return foundTexts1332    def waitText(self, text, *waitAnyTextArgs, **waitAnyTextKwArgs):1333        """1334        Wait until text appears in any view item.1335        Parameters:1336          text (string):1337                text to be waited for.1338          partial (boolean, optional):1339                refer to verifyText. The default is False.1340          uiautomatorDump (boolean, optional):1341                use uiautomator to read view dump from the device.1342                If not given, uiautomatorDump() default will be used.1343          waitTime, pollDelay, beforeRefresh, afterRefresh (optional):1344                refer to wait documentation.1345        Returns True if text appeared within given time limit,1346        otherwise False.1347        Updates the last view if the text is not found in the latest view1348        and waitTime > 0.1349        """1350        return self.waitAnyText(1351            [text], *waitAnyTextArgs, **waitAnyTextKwArgs) != []1352    def wake(self):1353        """1354        Force the device to wake up.1355        """1356        return self.existingConnection().sendWake()1357    def _loadDeviceAndTestINIs(self, homeDir, deviceName, iniFile):1358        if deviceName != None:1359            _deviceIniFilename = homeDir + os.sep + "etc" + os.sep + deviceName + ".ini"1360            self.loadConfig(_deviceIniFilename, override=True, level="device")1361        if iniFile:1362            self.loadConfig(iniFile, override=True, level="test")1363class Ini:1364    """1365    Container for device configuration loaded from INI files.1366    INI file syntax:1367    [section1]1368    key1 = value11369    ; commented = out1370    # commented = out1371    """1372    def __init__(self, iniFile=None):1373        """1374        Initialise the container, optionally with an initial configuration.1375        Parameters:1376          iniFile (file object, optional):1377                  load the initial configuration from iniFile.1378                  The default is None: start with empty configuration.1379        """1380        # _conf is a dictionary:1381        # (section, key) -> value1382        self._conf = {}1383        if iniFile:1384            self.addFile(iniFile)1385    def addFile(self, iniFile, override=True):1386        """1387        Add values from a file to the current configuration.1388        Parameters:1389          iniFile (file object):1390                  load values from this file object.1391          override (boolean, optional):1392                  If True, loaded values override existing values.1393                  Otherwise, only currently undefined values are1394                  loaded. The default is True.1395        """1396        for line in iniFile:1397            line = line.strip()1398            if line.startswith('[') and line.endswith(']'):1399                section = line[1:-1].strip()1400            elif line.startswith(";") or line.startswith("#"):1401                continue1402            elif '=' in line:1403                key, value = line.split('=', 1)1404                if override or (section, key.strip()) not in self._conf:1405                    self._conf[(section, key.strip())] = value.strip()1406    def sections(self):1407        """1408        Returns list of sections in the current configuration.1409        """1410        return list(set([k[0] for k in self._conf.keys()]))1411    def keys(self, section):1412        """1413        Returns list of keys in a section in the current configuration.1414        Parameters:1415          section (string):1416                  the name of the section.1417        """1418        return [k[1] for k in self._conf.keys() if k[0] == section]1419    def dump(self):1420        """1421        Returns the current configuration as a single string in the1422        INI format.1423        """1424        lines = []1425        for section in sorted(self.sections()):1426            lines.append("[%s]" % (section,))1427            for key in sorted(self.keys(section)):1428                lines.append("%-16s = %s" % (key, self._conf[(section, key)]))1429            lines.append("")1430        return "\n".join(lines)1431    def set(self, section, key, value):1432        """1433        Set new value for a key in a section.1434        Parameters:1435          section, key (strings):1436                  the section, the key.1437          value (string):1438                  the new value. If not string already, it will be1439                  converted to string, and it will be loaded as a1440                  string when loaded from file object.1441        """1442        self._conf[(section, key)] = str(value)1443    def value(self, section, key, default=""):1444        """1445        Returns the value (string) associated with a key in a section.1446        Parameters:1447          section, key (strings):1448                  the section and the key.1449          default (string, optional):1450                  the default value to be used and stored if there is1451                  no value associated to the key in the section. The1452                  default is the empty string.1453        Reading a value of an undefined key in an undefined section1454        adds the key and the section to the configuration with the1455        returned (the default) value. This makes all returned values1456        visible in dump().1457        """1458        if not (section, key) in self._conf:1459            self._conf[(section, key)] = default1460        return self._conf[(section, key)]1461# For backward compatibility, someone might be using old _DeviceConf1462_DeviceConf = Ini1463class ViewItem(fmbtgti.GUIItem):1464    """1465    ViewItem holds the information of a single GUI element.1466    """1467    _boundsRegEx = re.compile(r'\[([0-9]+),([0-9]+)\]\[([0-9]+),([0-9]+)\]')1468    def __init__(self, className, code, indent, properties, parent, rawProps, dumpFilename, displayToScreen):1469        self._p = properties1470        self._parent = parent1471        self._className = className1472        self._code = code1473        self._indent = indent1474        self._children = []1475        self._parentsVisible = True1476        if "resource-id" in self._p:1477            self._id = self._p["resource-id"].split(":", 1)[-1]1478        else:1479            self._id = self.property("mID")1480        self._rawProps = ""1481        if not "bounds" in self._p:1482            if not "scrolling:mScrollX" in self._p:1483                self._p["scrolling:mScrollX"] = 01484                self._p["scrolling:mScrollY"] = 01485            self._visible = self._p.get("getVisibility()", "") == "VISIBLE"1486            if "text:mText" in self._p:1487                self._text = self._p["text:mText"]1488            else:1489                self._text = None1490        else:1491            self._visible = True1492            self._text = self._p["text"]1493        fmbtgti.GUIItem.__init__(self, className, self._calculateBbox(displayToScreen), dumpFilename)1494    def addChild(self, child):1495        child._parentsVisible = self.visibleBranch()1496        self._children.append(child)1497    def _calculateBbox(self, displayToScreen):1498        if "bounds" in self._p:1499            try:1500                left, top, right, bottom = [1501                    int(v) for v in1502                    ViewItem._boundsRegEx.findall(self._p["bounds"])[0]]1503            except IndexError:1504                raise ValueError('invalid bounds "%s"' % (self._p["bounds"],))1505            width = right - left1506            height = bottom - top1507        elif "layout:getLocationOnScreen_x()" in self._p:1508            left = int(self._p["layout:getLocationOnScreen_x()"])1509            top = int(self._p["layout:getLocationOnScreen_y()"])1510            height = int(self._p["layout:getHeight()"])1511            width = int(self._p["layout:getWidth()"])1512        elif "layout:mLeft" in self._p:1513            left = int(self._p["layout:mLeft"])1514            top = int(self._p["layout:mTop"])1515            parent = self._parent1516            while parent:1517                pp = parent._p1518                left += int(pp["layout:mLeft"]) - int(pp["scrolling:mScrollX"])1519                top += int(pp["layout:mTop"]) - int(pp["scrolling:mScrollY"])1520                parent = parent._parent1521            height = int(self._p["layout:getHeight()"])1522            width = int(self._p["layout:getWidth()"])1523        else:1524            raise ValueError("bounding box not found, layout fields missing")1525        screenLeft, screenTop = displayToScreen(left, top)1526        screenRight, screenBottom = displayToScreen(left + width, top + height)1527        return (screenLeft, screenTop, screenRight, screenBottom)1528    def children(self):   return self._children1529    def className(self):  return self._className1530    def code(self):       return self._code1531    def indent(self):     return self._indent1532    def id(self):         return self._id1533    def parent(self):     return self._parent1534    def properties(self): return self._p1535    def property(self, propertyName):1536        return self._p.get(propertyName, None)1537    def visibleBranch(self):1538        """Returns True if this item and all items containing this are visible1539        up to the root node"""1540        return self._parentsVisible and self.visible()1541    def text(self):1542        return self._text1543    def content_desc(self):1544        if "content-desc" in self._p:1545            return self._p["content-desc"]1546        elif "accessibility:getContentDescription()" in self._p:1547            return self._p["accessibility:getContentDescription()"]1548        else:1549            return None1550    def visible(self):1551        return self._visible1552    def dump(self):1553        p = self._p1554        return ("ViewItem(\n\tchildren = %d\n\tclassName = '%s'\n\tcode = '%s'\n\t" +1555                "indent = %d\n\tproperties = {\n\t\t%s\n\t})") % (1556            len(self._children), self._className, self._code, self._indent,1557            '\n\t\t'.join(['"%s": %s' % (key, p[key]) for key in sorted(p.keys())]))1558    def dumpProperties(self):1559        rv = []1560        if self._p:1561            for key in [k for k in sorted(self._p.keys()) if not "layout:" in k and not "padding:" in k and not "drawing:" in k]: # sorted(self._p.keys()): # [k for k in sorted(self._p.keys()) if not ":" in k]:1562                rv.append("%s=%s" % (key, self._p[key]))1563        return "\n".join(rv)1564    def __str__(self):1565        if self.text():1566            text = ", text=%s" % (repr(self.text()),)1567        else:1568            text = ""1569        if "content-desc" in self._p and self._p["content-desc"]:1570            text += ", content_desc=%s" % (repr(self.content_desc(),))1571        return ("ViewItem(className=%s, id=%s, bbox=%s%s)"  % (1572                repr(self._className), repr(self.id()), self.bbox(), text))1573class View(object):1574    """1575    View provides interface to screen dumps from Android. It parses1576    the dump to a hierarchy of ViewItems. find* methods enable searching1577    for ViewItems based on their properties.1578    """1579    def __init__(self, screenshotDir, serialNumber, dump, displayToScreen=None,1580                 itemOnScreen=None, intCoords=None):1581        self.screenshotDir = screenshotDir1582        self.serialNumber = serialNumber1583        self._viewItems = []1584        self._errors = []1585        self._lineRegEx = re.compile("(?P<indent>\s*)(?P<class>[\w.$]+)@(?P<id>[0-9A-Fa-f]{4,8} )(?P<properties>.*)")1586        self._olderAndroidLineRegEx = re.compile("(?P<indent>\s*)(?P<class>[\w.$]+)@(?P<id>\w)(?P<properties>.*)")1587        self._propRegEx = re.compile("(?P<prop>(?P<name>[^=]+)=(?P<len>\d+),)(?P<data>[^\s]* ?)")1588        self._dump = dump1589        self._rawDumpFilename = self.screenshotDir + os.sep + fmbtgti._filenameTimestamp() + "-" + self.serialNumber + ".view"1590        file(self._rawDumpFilename, "w").write(self._dump)1591        if displayToScreen == None:1592            displayToScreen = lambda x, y: (x, y)1593        if itemOnScreen == None:1594            itemOnScreen = lambda item: True1595        self._itemOnScreen = itemOnScreen1596        if intCoords == None:1597            intCoords = lambda x, y: (int(x), int(y))1598        self._intCoords = intCoords1599        try:1600            if dump.startswith("<?xm"):1601                self._parseUIAutomatorDump(dump, self._rawDumpFilename, displayToScreen)1602            else:1603                self._parseDump(dump, self._rawDumpFilename, displayToScreen)1604        except Exception, e:1605            self._errors.append((-1, "", "Parser error"))1606    def viewItems(self): return self._viewItems1607    def errors(self): return self._errors1608    def dumpRaw(self): return self._dump1609    def dumpItems(self, itemList = None):1610        if itemList == None: itemList = self._viewItems1611        l = []1612        for i in itemList:1613            l.append(self._dumpItem(i))1614        return '\n'.join(l)1615    def dumpTree(self, rootItem = None):1616        l = []1617        if rootItem != None:1618            l.extend(self._dumpSubTree(rootItem, 0))1619        else:1620            for i in self._viewItems:1621                if i._indent == 0:1622                    l.extend(self._dumpSubTree(i, 0))1623        return '\n'.join(l)1624    def _dumpSubTree(self, viewItem, indent):1625        l = []1626        i = viewItem1627        l.append(" "*indent + self._dumpItem(viewItem))1628        for i in viewItem.children():1629            l.extend(self._dumpSubTree(i, indent + 4))1630        return l1631    def _dumpItem(self, viewItem):1632        i = viewItem1633        if i.text() != None: t = '"%s"' % (i.text(),)1634        else: t = None1635        return "id=%s cls=%s text=%s bbox=%s vis=%s" % (1636            i.id(), i.className(), t, i.bbox(), i.visibleBranch())1637    def filename(self):1638        return self._rawDumpFilename1639    def findItems(self, comparator, count=-1, searchRootItem=None, searchItems=None, onScreen=False):1640        """1641        Returns list of ViewItems to which comparator returns True.1642        Parameters:1643          comparator (function that takes one parameter (ViewItem))1644                  returns True for all accepted items.1645          count (integer, optional):1646                  maximum number of items to be returned.1647                  The default is -1 (unlimited).1648          searchRootItem (ViewItem, optional):1649                  search only among items that are children of1650                  searchRootItem. The default is None (search from all).1651          searchItems (list of ViewItems, optional):1652                  search only among given items. The default is None,1653                  (search from all).1654          onScreen (boolean, optional):1655                  search only among items that are on screen. The1656                  default is False.1657        """1658        foundItems = []1659        if count == 0: return foundItems1660        if searchRootItem != None:1661            # find from searchRootItem and its children1662            if comparator(searchRootItem) and (1663                    not onScreen or1664                    searchRootItem.visibleBranch() and self._itemOnScreen(searchRootItem)):1665                foundItems.append(searchRootItem)1666            for c in searchRootItem.children():1667                foundItems.extend(self.findItems(comparator, count=count-len(foundItems), searchRootItem=c, onScreen=onScreen))1668        else:1669            if searchItems != None:1670                # find from listed items only1671                searchDomain = searchItems1672            else:1673                # find from all items1674                searchDomain = self._viewItems1675            for i in searchDomain:1676                if comparator(i) and (1677                        not onScreen or1678                        i.visibleBranch() and self._itemOnScreen(i)):1679                    foundItems.append(i)1680                    if count > 0 and len(foundItems) >= count:1681                        break1682        return foundItems1683    def findItemsByText(self, text, partial=False, count=-1, searchRootItem=None, searchItems=None, onScreen=False):1684        """1685        Returns list of ViewItems with given text.1686        """1687        if partial:1688            c = lambda item: item.text().find(text) != -1 if item.text() != None else False1689        else:1690            c = lambda item: item.text() == text1691        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)1692    def findItemsById(self, id, count=-1, searchRootItem=None, searchItems=None, onScreen=False):1693        """1694        Returns list of ViewItems with given id.1695        """1696        c = lambda item: item.id() == id1697        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)1698    def findItemsByClass(self, className, partial=True, count=-1, searchRootItem=None, searchItems=None, onScreen=False):1699        """1700        Returns list of ViewItems with given class.1701        """1702        if partial: c = lambda item: item.className().find(className) != -11703        else: c = lambda item: item.className() == className1704        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)1705    def findItemsByIdAndClass(self, id, className, partial=True, count=-1, searchRootItem=None, searchItems=None, onScreen=False):1706        """1707        Returns list of ViewItems with given id and class.1708        """1709        idOk = self.findItemsById(id, count=-1, searchRootItem=searchRootItem, onScreen=onScreen)1710        return self.findItemsByClass(className, partial=partial, count=count, searchItems=idOk, onScreen=onScreen)1711    def findItemsByContentDesc(self, content_desc, partial=False, count=-1, searchRootItem=None, searchItems=None, onScreen=False):1712        """1713        Returns list of ViewItems with given content-desc.1714        Works on uiautomatorDumps only.1715        """1716        if partial:1717            c = lambda item: item.content_desc().find(content_desc) != -11718        else:1719            c = lambda item: item.content_desc() == content_desc1720        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)1721    def findItemsByRawProps(self, s, count=-1, searchRootItem=None, searchItems=None, onScreen=False):1722        """1723        Returns list of ViewItems with given string in properties.1724        """1725        c = lambda item: item._rawProps.find(s) != -11726        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)1727    def findItemsByPos(self, pos, count=-1, searchRootItem=None, searchItems=None, onScreen=False):1728        """1729        Returns list of ViewItems whose bounding box contains the position.1730        Parameters:1731          pos (pair of floats (0.0..0.1) or integers (x, y)):1732                  coordinates that fall in the bounding box of found items.1733          other parameters: refer to findItems documentation.1734        Items are listed in ascending order based on area. They may1735        or may not be from the same branch in the widget hierarchy.1736        """1737        x, y = self._intCoords(pos)1738        c = lambda item: (item.bbox()[0] <= x <= item.bbox()[2] and item.bbox()[1] <= y <= item.bbox()[3])1739        items = self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)1740        # sort from smallest to greatest area1741        area_items = [((i.bbox()[2] - i.bbox()[0]) * (i.bbox()[3] - i.bbox()[1]), i) for i in items]1742        return [i for _, i in sorted(area_items)]1743    def findItemsInRegion(self, bbox, count=-1, searchRootItem=None, searchItems=None, onScreen=False):1744        """1745        Returns list of ViewItems whose bounding box is within the region.1746        Parameters:1747          bbox (four-tuple of floats (0.0..1.0) or integers):1748                  bounding box that specifies search region1749                  (left, top, right, bottom).1750          other parameters: refer to findItems documentation.1751        Returned items are listed in ascending order based on area.1752        """1753        left, top = self._intCoords((bbox[0], bbox[1]))1754        right, bottom = self._intCoords((bbox[2], bbox[3]))1755        c = lambda item: (left <= item.bbox()[0] <= item.bbox()[2] <= right and1756                          top <= item.bbox()[1] <= item.bbox()[3] <= bottom)1757        items = self.findItems(c, count=count, searchRootItem=searchRootItem,1758                               searchItems=searchItems, onScreen=onScreen)1759        area_items = [((i.bbox()[2] - i.bbox()[0]) * (i.bbox()[3] - i.bbox()[1]), i) for i in items]1760        return [i for _, i in sorted(area_items)]1761    def items(self):1762        """1763        Returns list of all items in the view1764        """1765        return fmbtgti.sortItems(self._viewItems, "topleft")1766    def save(self, fileOrDirName):1767        """1768        Save view dump to a file.1769        """1770        shutil.copy(self._rawDumpFilename, fileOrDirName)1771    def _parseUIAutomatorDump(self, dump, rawDumpFilename, displayToScreen):1772        """1773        Process XML output from "uiautomator dump" and create1774        a tree of ViewItems.1775        """1776        def add_elt(elt, parent, indent, results):1777            if ("resource-id" in elt.attrib and1778                "bounds" in elt.attrib):1779                try:1780                    vi = ViewItem(elt.attrib["class"],1781                                  elt.attrib["resource-id"].split(":", 1)[-1],1782                                  indent,1783                                  elt.attrib,1784                                  parent,1785                                  "",1786                                  self._rawDumpFilename,1787                                  displayToScreen)1788                    results.append(vi)1789                    if parent:1790                        parent.addChild(self._viewItems[-1])1791                except Exception, e:1792                    adapterlog("parseUIAutomatorDump error: %s" % (e,))1793                    vi = parent1794            else:1795                vi = parent1796            for child in elt.getchildren():1797                add_elt(child, vi, indent + 1, results)1798        self._viewItems = []1799        tree = xml.etree.ElementTree.parse(rawDumpFilename)1800        root = tree.getroot()1801        add_elt(root, None, 0, self._viewItems)1802        return self._viewItems1803    def _parseDump(self, dump, rawDumpFilename, displayToScreen):1804        """1805        Process the raw window service dump data and create a tree of1806        ViewItems.1807        """1808        if not isinstance(dump, unicode):1809            try:1810                dump = unicode(dump, "utf-8")1811            except UnicodeDecodeError, e:1812                self._errors.append((0, 0, "converting to unicode failed: %s" % (e,)))1813        # This code originates from tema-android-adapter-3.2,1814        # AndroidAdapter/guireader.py.1815        self._viewItems = []1816        cellLayout = ""1817        parent = None1818        previousItem = None1819        currentIndent = 01820        visible = True1821        self.TOP_PAGED_VIEW = ""1822        last_line = set(["DONE", "DONE."])1823        for lineIndex, line in enumerate(dump.splitlines()):1824            if line in last_line:1825                break1826            # separate indent, class and properties for each GUI object1827            # TODO: branch here according to self._androidVersion1828            matcher = self._lineRegEx.match(line)1829            if not matcher:1830                # FIXME: this hack falls back to old format,1831                # should branch according to self._androidVersion!1832                matcher = self._olderAndroidLineRegEx.match(line)1833                if not matcher:1834                    self._errors.append((lineIndex + 1, line, "illegal line"))1835                    continue # skip this line1836            className = matcher.group("class")1837            # Indent specifies the hierarchy level of the object1838            indent = len(matcher.group("indent"))1839            # If the indent is bigger that previous, this object is a1840            # child for the previous object1841            if indent > currentIndent:1842                parent = self._viewItems[-1]1843            elif indent < currentIndent:1844                for tmp in range(0, currentIndent - indent):1845                    parent = parent.parent()1846            currentIndent = indent1847            propertiesData = matcher.group("properties")1848            properties = {}1849            index = 01850            x = 01851            y = 01852            # Process the properties of each GUI object1853            while index < len(propertiesData):1854                # Separate name and value for each property [^=]*=1855                propMatch = self._propRegEx.match(propertiesData[index:-1])1856                if not propMatch:1857                    self._errors.append((lineIndex, line,1858                                         "property parse error"))1859                    break1860                name = propMatch.group("name")1861                if not name:1862                    self._errors.append(1863                        (lineIndex, line,1864                         'illegal property name "%s"' % (name,)))1865                    break1866                try:1867                    dataLength = int(propMatch.group("len"))1868                except ValueError:1869                    self._errors.append(1870                        (lineIndex, line,1871                         'illegal length (int) "%s"' % (propMatch.group("len"),)))1872                    break1873                data = propMatch.group("data")1874                dataStart = index + propMatch.start("data")1875                if len(data) < dataLength:1876                    if not data:1877                        self._errors.append(1878                            (lineIndex, line,1879                             'property "%s": data missing, expected %s' % (name, dataLength, len(data))))1880                        break1881                properties[name] = propertiesData[dataStart:dataStart + dataLength]1882                index = dataStart + dataLength + 11883            try:1884                vi = ViewItem(matcher.group("class"), matcher.group("id"), indent, properties, parent, matcher.group("properties"), self._rawDumpFilename, displayToScreen)1885                self._viewItems.append(vi)1886                if parent:1887                    parent.addChild(self._viewItems[-1])1888            except Exception, e:1889                self._errors.append(1890                    (lineIndex, line,1891                     "creating view item failed (%s: %s)" % (type(e), e)))1892        return self._viewItems1893    def __str__(self):1894        return 'View(items=%s, dump="%s")' % (1895            len(self._viewItems), self._rawDumpFilename)1896class _AndroidDeviceConnection(fmbtgti.GUITestConnection):1897    """1898    Connection to the Android Device being tested.1899    """1900    _m_host = os.getenv("FMBTANDROID_ADB_FORWARD_HOST", 'localhost')1901    _m_port = int(os.getenv("FMBTANDROID_ADB_FORWARD_PORT", random.randint(20000, 29999)))1902    _w_host = _m_host1903    def __init__(self, serialNumber, **kwArgs):1904        fmbtgti.GUITestConnection.__init__(self)1905        self._serialNumber = serialNumber1906        self._adbPort = kwArgs.pop("adbPort", None)1907        self._monkeyPortForward = kwArgs.pop(1908            "adbForwardPort", _AndroidDeviceConnection._m_port)1909        self._windowPortForward = kwArgs.pop(1910            "windowPortForward", self._monkeyPortForward + 1)1911        self._stopOnError = kwArgs.pop("stopOnError", True)1912        self._monkeyOptions = kwArgs.pop("monkeyOptions", [])1913        self._screencapArgs = kwArgs.pop("screencapArgs", [])1914        self._screencapFormat = kwArgs.pop("screencapFormat", "raw")1915        self.setScreenToDisplayCoords(1916            kwArgs.pop("screenToDisplay", lambda x, y: (x, y)))1917        self.setDisplayToScreenCoords(1918            kwArgs.pop("displayToScreen", lambda x, y: (x, y)))1919        if kwArgs:1920            raise TypeError('_AndroidDeviceConnection.__init__() got an '1921                            'unexpected keyword argument %s=%s' % (1922                kwArgs.keys()[0], repr(kwArgs[kwArgs.keys()[0]])))1923        self._detectFeatures()1924        self._emulatorSocket = None1925        try:1926            self._resetMonkey()1927            self._resetWindow()1928        finally:1929            # Next _AndroidDeviceConnection instance will use different ports1930            _AndroidDeviceConnection._m_port += 1001931    def __del__(self):1932        try: self._monkeySocket.close()1933        except: pass1934        try: self._emulatorSocket.close()1935        except: pass1936    def settings(self):1937        """Returns restorable property values"""1938        rv = {1939            "adbPort": self._adbPort,1940            "adbForwardPort": self._monkeyPortForward,1941            "stopOnError": self._stopOnError,1942            "monkeyOptions": self._monkeyOptions,1943            "screencapArgs": self._screencapArgs,1944            "screencapFormat": self._screencapFormat,1945            "screenToDisplay": self._screenToDisplay,1946            "displayToScreen": self._displayToScreen,1947        }1948        return rv1949    def target(self):1950        return self._serialNumber1951    def _cat(self, remoteFilename):1952        fd, filename = tempfile.mkstemp("fmbtandroid-cat-")1953        os.close(fd)1954        self._runAdb(["pull", remoteFilename, filename], 0, timeout=_LONG_TIMEOUT)1955        contents = file(filename).read()1956        os.remove(filename)1957        return contents1958    def _runAdb(self, adbCommand, expectedExitStatus=0, timeout=None):1959        if not self._stopOnError:1960            expect = None1961        else:1962            expect = expectedExitStatus1963        if self._adbPort:1964            adbPortArgs = ["-P", str(self._adbPort)]1965        else:1966            adbPortArgs = []1967        command = [_g_adbExecutable, "-s", self._serialNumber] + adbPortArgs1968        if type(adbCommand) == list or type(adbCommand) == tuple:1969            command.extend(adbCommand)1970        else:1971            command.append(adbCommand)1972        return _run(command, expectedExitStatus=expect, timeout=timeout)1973    def _emulatorCommand(self, command):1974        if not self._emulatorSocket:1975            try:1976                emulatorPort = int(re.findall("emulator-([0-9]*)", self._serialNumber)[0])1977            except (IndexError, ValueError):1978                raise FMBTAndroidError("emulator port detection failed")1979            try:1980                self._emulatorSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)1981                self._emulatorSocket.connect(("localhost", emulatorPort))1982            except socket.error, e:1983                raise FMBTAndroidError("connecting to the emulator failed: %s" % (e,))1984        self._emulatorSocket.sendall(command + "\n")1985        data = self._emulatorSocket.recv(4096)1986        try:1987            data = data.splitlines()[-1].strip()1988        except IndexError:1989            raise FMBTAndroidError("no response from the emulator")1990        if data.startswith("OK"):1991            return True, data1992        else:1993            return False, data1994    def _runSetupCmd(self, cmd, expectedExitStatus=0):1995        _adapterLog('setting up connections: "%s"' % (cmd,))1996        try:1997            if expectedExitStatus == None: # execute asynchronously1998                self._runAdb(cmd, expectedExitStatus)1999            else: # command is expected to exit2000                self._runAdb(cmd, expectedExitStatus, timeout=_SHORT_TIMEOUT)2001        except (FMBTAndroidRunError, AndroidDeviceNotFound), e:2002            _adapterLog("connection setup problem: %s" % (e,))2003            return False2004        return True2005    def _detectFeatures(self):2006        # check supported features2007        outputLines = self._runAdb(["shell", "getprop", "ro.build.version.release"],2008                                   timeout=_SHORT_TIMEOUT)[1].splitlines()2009        if len(outputLines) >= 1:2010            self._platformVersion = outputLines[0].strip().split("=")[-1]2011        else:2012            self._platformVersion = "N/A"2013        outputLines = self._runAdb(["shell", "id"],2014                                   timeout=_SHORT_TIMEOUT)[1].splitlines()2015        if len(outputLines) == 1 and "uid=0" in outputLines[0]:2016            self._shellUid0 = True2017        else:2018            self._shellUid0 = False2019        outputLines = self._runAdb(["shell", "su", "root", "id"],2020                                   timeout=_SHORT_TIMEOUT)[1].splitlines()2021        if len(outputLines) == 1 and "uid=0" in outputLines[0]:2022            self._shellSupportsSu = True2023        else:2024            self._shellSupportsSu = False2025        outputLines = self._runAdb(["shell", "tar"],2026                                   expectedExitStatus=EXITSTATUS_ANY,2027                                   timeout=_SHORT_TIMEOUT)[1].splitlines()2028        if len(outputLines) == 1 and "bin" in outputLines[0]:2029            self._shellSupportsTar = False2030        else:2031            self._shellSupportsTar = True2032        outputLines = self._runAdb(["shell", "echo -n foo | toybox base64"],2033                                   expectedExitStatus=EXITSTATUS_ANY,2034                                   timeout=_SHORT_TIMEOUT)[1].splitlines()2035        if len(outputLines) == 1 and "Zm9v" in outputLines[0]:2036            self._shellSupportsToyboxBase64 = True2037        else:2038            self._shellSupportsToyboxBase64 = False2039        outputLines = self._runAdb(["shell", "echo -n foo | uuencode -"],2040                                   expectedExitStatus=EXITSTATUS_ANY,2041                                   timeout=_SHORT_TIMEOUT)[1].splitlines()2042        if len(outputLines) > 0 and "begin" in outputLines[0]:2043            self._shellSupportsUuencode = True2044        else:2045            self._shellSupportsUuencode = False2046    def _resetWindow(self):2047        setupCommands = [["shell", "service" , "call", "window", "1", "i32", "4939"],2048                         ["forward", "tcp:"+str(self._windowPortForward), "tcp:4939"]]2049        for c in setupCommands:2050            self._runSetupCmd(c)2051    def _resetMonkey(self, timeout=12, pollDelay=.25):2052        tryKillingMonkeyOnFailure = 12053        failureCountSinceKill = 02054        endTime = time.time() + timeout2055        if self._shellUid0:2056            monkeyLaunch = ["monkey"]2057        elif self._shellSupportsSu:2058            monkeyLaunch = ["su", "root", "monkey"]2059        else:2060            monkeyLaunch = ["monkey"]2061        if self._monkeyOptions:2062            monkeyLaunch += self._monkeyOptions2063        while time.time() < endTime:2064            monkeyShellCmd = (" ".join(monkeyLaunch + ["--port", "1080"]) +2065                              " >/sdcard/fmbtandroid.monkey.outerr 2>&1")2066            _adapterLog('launching monkey: adb shell "%s"' % (monkeyShellCmd,))2067            self._runAdb(["shell", monkeyShellCmd], expectedExitStatus=None)2068            time.sleep(pollDelay)2069            if not self._runSetupCmd(["forward", "tcp:"+str(self._monkeyPortForward), "tcp:1080"]):2070                time.sleep(pollDelay)2071                failureCountSinceKill += 12072                continue2073            try:2074                self._monkeySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)2075                self._monkeySocket.connect((self._m_host, self._monkeyPortForward))2076                self._monkeySocket.setblocking(0)2077                self._monkeySocket.settimeout(5.0)2078                _ping = self._monkeyCommand("getvar build.version.release", retry=0)[1]2079                if len(_ping) > 0:2080                    return True2081            except Exception, e:2082                _, monkeyOutput, _ = self._runAdb(["shell", "cat /sdcard/fmbtandroid.monkey.outerr"],2083                                                  expectedExitStatus=EXITSTATUS_ANY,2084                                                  timeout=_SHORT_TIMEOUT)2085                if "/sdcard/fmbtandroid.monkey.outerr: No such file or directory" in monkeyOutput:2086                    msg = 'cannot read/write /sdcard on device %s' % (self._serialNumber,)2087                    _adapterLog(msg)2088                    raise AndroidConnectionError(msg)2089                elif "Error: Unknown option:" in monkeyOutput:2090                    uo = [l for l in monkeyOutput.splitlines() if "Error: Unknown option:" in l][0].split(":")[-1].strip()2091                    _adapterLog('detected an unknown option for monkey: "%s". Disabling it.' % (uo,))2092                    try:2093                        monkeyLaunch.remove(uo)2094                    except ValueError:2095                        pass2096                    continue2097                elif "Error binding to network socket" in monkeyOutput:2098                    _adapterLog('monkey network socket binding failed, killing old monkey')2099                    self.pkill("monkey")2100                    time.sleep(pollDelay)2101                    continue2102                _adapterLog("monkey connection failed, output: %s" % (monkeyOutput,))2103                failureCountSinceKill += 12104            time.sleep(pollDelay)2105            if failureCountSinceKill > 2 and tryKillingMonkeyOnFailure > 0:2106                self.pkill("monkey")2107                tryKillingMonkeyOnFailure -= 12108                failureCountSinceKill = 02109                time.sleep(pollDelay)2110        if self._stopOnError:2111            msg = 'Android monkey error: cannot connect to "adb shell monkey --port 1080" to device %s' % (self._serialNumber)2112            _adapterLog(msg)2113            raise AndroidConnectionError(msg)2114        else:2115            return False2116    def _monkeyCommand(self, command, retry=3):2117        try:2118            self._monkeySocket.sendall(command + "\n")2119            data = self._monkeySocket.recv(4096).strip()2120            if len(data) == 0 and retry > 0:2121                return self._monkeyCommand(command, retry-1)2122            if data == "OK":2123                return True, None2124            elif data.startswith("OK:"):2125                return True, data.split("OK:")[1]2126            _adapterLog("monkeyCommand failing... command: '%s' response: '%s'" % (command, data))2127            return False, None2128        except socket.error:2129            try: self._monkeySocket.close()2130            except: pass2131            if retry > 0:2132                self._resetMonkey()2133                return self._monkeyCommand(command, retry=retry-1)2134            else:2135                raise AndroidConnectionError('Android monkey socket connection lost while sending command "%s"' % (command,))2136    def install(self, filename, lock, reinstall, downgrade,2137                sdcard, algo, key, iv):2138        cmd = ["install"]2139        if lock:2140            cmd.append("-l")2141        if reinstall:2142            cmd.append("-r")2143        if downgrade:2144            cmd.append("-d")2145        if sdcard:2146            cmd.append("-s")2147        if algo != None:2148            cmd.extend(["--algo", algo])2149        if key != None:2150            cmd.extend(["--key", key])2151        if iv != None:2152            cmd.extend(["--iv", iv])2153        cmd.append(filename)2154        status, output, error = self._runAdb(cmd, [0, 1], timeout=_LONG_TIMEOUT)2155        if "Success" in output:2156            return True2157        else:2158            return output + "\n" + error2159    def uninstall(self, apkname, keepData):2160        cmd = ["uninstall"]2161        if keepData:2162            cmd.append("-k")2163        cmd.append(apkname)2164        status, output, error = self._runAdb(2165            cmd, expectedExitStatus=EXITSTATUS_ANY, timeout=_LONG_TIMEOUT)2166        if "Success" in output:2167            return True2168        else:2169            return False2170    def pkill(self, pattern, signal=15, exact=False):2171        """send signal to all processes where process name contains pattern"""2172        _, ps, _ = self._runAdb(["shell", "ps"], timeout=_SHORT_TIMEOUT)2173        if self._shellSupportsSu:2174            shell_kill = ["shell", "su", "root", "kill"]2175        else:2176            shell_kill = ["shell", "kill"]2177        pids = []2178        for line in [l.strip() for l in ps.splitlines()]:2179            fields = line.split()2180            if len(fields) > 7:2181                if exact:2182                    if pattern == fields[7]:2183                        pids.append(fields[1])2184                else:2185                    if pattern in " ".join(fields[7:]):2186                        pids.append(fields[1])2187        if pids:2188            _adapterLog(str(shell_kill + ["-" + str(signal)] + pids))2189            self._runAdb(shell_kill + ["-" + str(signal)] + pids,2190                         expectedExitStatus=EXITSTATUS_ANY,2191                         timeout=_SHORT_TIMEOUT)2192            return True2193        else:2194            return False2195    def recvPlatformVersion(self):2196        return self._platformVersion2197    def reboot(self, reconnect, firstBootAfterFlashing, timeout):2198        if firstBootAfterFlashing:2199            self._runAdb("root", expectedExitStatus=EXITSTATUS_ANY,2200                         timeout=_SHORT_TIMEOUT)2201            time.sleep(2)2202            self._runAdb(["shell", "rm",2203                          "/data/data/com.android.launcher/shared_prefs/com.android.launcher2.prefs.xml"],2204                         expectedExitStatus=EXITSTATUS_ANY,2205                         timeout=_SHORT_TIMEOUT)2206        self._runAdb("reboot", expectedExitStatus=EXITSTATUS_ANY)2207        _adapterLog("rebooting " + self._serialNumber)2208        if reconnect:2209            time.sleep(2)2210            endTime = time.time() + timeout2211            status, _, _ = self._runAdb("wait-for-device", expectedExitStatus=None, timeout=timeout)2212            if status != 0:2213                raise AndroidDeviceNotFound('"timeout -k 1 %s adb wait-for-device" status %s' % (timeout, status))2214            self._detectFeatures()2215            while time.time() < endTime:2216                try:2217                    if self._resetMonkey(timeout=1, pollDelay=1):2218                        break2219                except AndroidConnectionError:2220                    pass2221                time.sleep(1)2222            else:2223                msg = "reboot: reconnecting to " + self._serialNumber + " failed"2224                _adapterLog(msg)2225                raise AndroidConnectionError(msg)2226            self._resetWindow()2227        return True2228    def recvVariable(self, variableName):2229        ok, value = self._monkeyCommand("getvar " + variableName)2230        if ok: return value2231        else:2232            # LOG: getvar variableName failed2233            return None2234    def recvScreenSize(self):2235        _, output, _ = self._runAdb(["shell", "dumpsys", "display"], 0,2236                                    timeout=_SHORT_TIMEOUT)2237        try:2238            # parse default display properties2239            ddName, ddWidth, ddHeight, ddWdpi, ddHdpi = re.findall(2240                r'DisplayDeviceInfo\{[^,]*"([^"]*)"[:,] ([0-9]*) x ([0-9]*),.*, ([0-9.]*) x ([0-9.]*) dpi,.*FLAG_DEFAULT_DISPLAY.*\}',2241                output)[0]2242            ddWidth, ddHeight = int(ddWidth), int(ddHeight)2243        except (IndexError, ValueError), e:2244            _adapterLog('recvScreenSize: cannot read size from "%s"' %2245                        (output,))2246            raise FMBTAndroidError('cannot read screen size from dumpsys')2247        vpWidth, vpHeight = self.recvDefaultViewportSize()2248        if ((vpWidth > vpHeight) and (ddWidth < ddHeight) or2249            (vpWidth < vpHeight) and (ddWidth > ddHeight)):2250            ddWidth, ddHeight = ddHeight, ddWidth2251        return int(ddWidth), int(ddHeight)2252    def recvDefaultViewportSize(self):2253        _, output, _ = self._runAdb(["shell", "dumpsys", "display"], 0,2254                                    timeout=_SHORT_TIMEOUT)2255        try:2256            _, w, h = re.findall("mDefaultViewport(\[0\])?=DisplayViewport\{.*deviceWidth=([0-9]*), deviceHeight=([0-9]*)\}", output)[0]2257            width = int(w)2258            height = int(h)2259        except (IndexError, ValueError), e:2260            _adapterLog('recvScreenSize: cannot read size from "%s"' %2261                        (output,))2262            raise FMBTAndroidError('cannot read screen size from dumpsys')2263        return width, height2264    def recvCurrentDisplayOrientation(self):2265        _, output, _ = self._runAdb(["shell", "dumpsys", "display"], 0,2266                                    timeout=_SHORT_TIMEOUT)2267        s = re.findall("mCurrentOrientation=([0-9])", output)2268        if s:2269            return int(s[0])2270        else:2271            return None2272    def recvDisplayPowered(self):2273        _, output, _ = self._runAdb(["shell", "dumpsys", "power"], 0,2274                                    timeout=_SHORT_TIMEOUT)2275        s = re.findall("Display Power: state=(OFF|ON)", output)2276        if s:2277            return s[0] == "ON"2278        else:2279            return None2280    def recvShowingLockscreen(self):2281        _, output, _ = self._runAdb(["shell", "dumpsys", "window"], 0,2282                                    timeout=_SHORT_TIMEOUT)2283        s = re.findall("mShowingLockscreen=(true|false)", output)2284        if s:2285            if s[0] == "true":2286                return True2287            else:2288                return False2289        else:2290            return None2291    def recvLastAccelerometer(self):2292        _, output, _ = self._runAdb(["shell", "dumpsys", "sensorservice"], 0,2293                                    timeout=_SHORT_TIMEOUT)2294        s = re.findall("3-axis Accelerometer.*last=<([- .0-9]*),([- .0-9]*),([- .0-9]*)>", output)2295        try:2296            rv = tuple([float(d) for d in s[0]])2297        except (IndexError, ValueError):2298            rv = (None, None, None)2299        return rv2300    def sendAcceleration(self, abc):2301        """abc is a tuple of 1, 2 or 3 floats, new accelerometer readings"""2302        try:2303            self._emulatorCommand("sensor set acceleration %s" %2304                                  (":".join([str(value) for value in abc]),))2305        except FMBTAndroidError, e:2306            raise FMBTAndroidError(2307                "accelerometer can be set only on emulator (%s)" % (e,))2308        return True2309    def sendAccelerometerRotation(self, value):2310        if value:2311            sendValue = "i:1"2312        else:2313            sendValue = "i:0"2314        try:2315            self._runAdb(["shell", "content", "insert",2316                          "--uri", "content://settings/system",2317                          "--bind", "name:s:accelerometer_rotation",2318                          "--bind", "value:" + sendValue],2319                         expectedExitStatus=0,2320                         timeout=_SHORT_TIMEOUT)2321        except Exception:2322            return False2323        return True2324    def recvAccelerometerRotation(self):2325        try:2326            _, output, _ = self._runAdb(2327                ["shell", "content", "query",2328                 "--uri", "content://settings/system/accelerometer_rotation"],2329                timeout=_SHORT_TIMEOUT)2330            s = re.findall("value=(.*)", output)[0]2331            return int(s) == 1 # True if accelerometer_rotation is enabled2332        except Exception:2333            return None2334    def sendDeviceLog(self, msg, priority, tag):2335        cmd = ["shell", "log", "-p", priority, "-t", tag, msg]2336        status, out, err = self._runAdb(cmd, [0, 124], timeout=_SHORT_TIMEOUT)2337        if status == 124:2338            errormsg = "log timeout: %s" % (["adb"] + cmd)2339            _adapterLog(errormsg)2340            raise FMBTAndroidError(errormsg)2341        return True2342    def sendUserRotation(self, rotation):2343        allowedRotations = [ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270]2344        if not rotation in allowedRotations:2345            raise ValueError("invalid rotation: %s, use one of %s" %2346                             (allowedRotations,))2347        sendValue = "i:%s" % (rotation,)2348        try:2349            self._runAdb(["shell", "content", "insert",2350                          "--uri", "content://settings/system",2351                          "--bind", "name:s:user_rotation",2352                          "--bind", "value:" + sendValue],2353                         timeout=_SHORT_TIMEOUT)2354        except Exception:2355            return False2356        return True...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
