Best Python code snippet using fMBT_python
eyenfinger.py
Source:eyenfinger.py
...201# _inputKeyNameCodeMap is a dictionary keyName -> keyCode202_inputKeyNameCodeMap = {}203for code, name in enumerate(InputKeys):204 _inputKeyNameCodeMap[name] = code205def _inputKeyNameToCode(keyName):206 if keyName in _inputKeyNameCodeMap:207 return _inputKeyNameCodeMap[keyName]208 elif keyName in _inputKeyShorthands:209 return _inputKeyNameCodeMap[_inputKeyShorthands[keyName]]210 else:211 raise ValueError('Invalid key name "%s"' % (keyName,))212def error(msg, exitstatus=1):213 sys.stderr.write("eyenfinger: %s\n" % (msg,))214 sys.exit(1)215def printEventsFromFile(filename):216 fd = os.open(filename, os.O_RDONLY)217 try:218 while 1:219 evString = os.read(fd, struct.calcsize(_InputEventStructSpec))220 if not evString: break221 tim, tus, typ, cod, val = struct.unpack(_InputEventStructSpec, evString)222 if cod < len(InputKeys):223 nam = InputKeys[cod]224 else:225 nam = "N/A"226 print "time: %8s, susc: %8s, type: %8s, keyCode: %5s name: %10s value: %8s" % \227 (tim, tus, typ, cod, nam, val)228 finally:229 os.close(fd)230def printEventsFromDevice(deviceName):231 devices = dict(_listInputDevices())232 if not deviceName in devices:233 error('Unknown device "%s". Available devices: %s' %234 (deviceName, sorted(devices.keys())))235 else:236 printEventsFromFile(devices[deviceName])237def _exitHandler():238 shutil.rmtree(_g_tempdir, ignore_errors=True)239atexit.register(_exitHandler)240def _runcmd(cmd):241 global _g_last_runcmd_error242 p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),243 stdout=subprocess.PIPE, stderr=subprocess.PIPE)244 output = p.stdout.read()245 exit_status = p.wait()246 _g_last_runcmd_error = p.stderr.read()247 if exit_status != 0:248 _log("runcmd: %s" % (cmd,))249 _log("exit status: " + str(exit_status))250 _log("stdout: " + output)251 _log("stderr: " + _g_last_runcmd_error)252 else:253 p.stderr.read()254 return exit_status, output255def _runDrawCmd(inputfilename, cmd, outputfilename):256 if not _g_defaultDelayedDrawing:257 return _runcmd([fmbt_config.imagemagick_convert,258 inputfilename] + cmd + [outputfilename])259 # Do delayed drawing to save test execution time. If the output260 # file does not exist, just copy inputfile to outputfile and start261 # logging delayed draw commands to262 # outputfile.delayeddraw. Otherwise append latest command to263 # outputfile.delayeddraw.264 delayedCmd = '%s "%s" "%s" "%s"\n' % (265 fmbt_config.imagemagick_convert,266 outputfilename, '%s' % ('" "'.join(cmd)), outputfilename)267 delayedDrawFilename = outputfilename + ".delayeddraw"268 try:269 if os.access(outputfilename, os.R_OK) == False:270 shutil.copy(inputfilename, outputfilename)271 file(delayedDrawFilename, "w").write(delayedCmd)272 else:273 file(delayedDrawFilename, "a").write(delayedCmd)274 except:275 _log("error on delayed drawing: %s" % (delayedCmd,))276 raise277 _log("delayed drawing: %s" % (delayedCmd,))278 return (0, "")279def _safeForShell(s):280 # convert all non-ascii and bad chars to _281 try: s = unicode(s, "utf-8")282 except: pass283 return ''.join([(c, "_")[ord(c)>128 or c in "'\"\\`"] for c in s])284def _coordsToInt((x,y), (width, height)=(None, None)):285 """286 Convert percentages to screen coordinates287 """288 if (width == None or height == None):289 width, height = screenSize()290 if 0.0 <= x <= 1.0 and type(x) == float:291 x = int(round(x * width))292 else:293 x = int(x)294 if 0.0 <= y <= 1.0 and type(y) == float:295 y = int(round(y * height))296 else:297 y = int(y)298 return (x, y)299def setPreprocessFilter(preprocess):300 global _g_preprocess301 _g_preprocess = preprocess302def iSetDefaultClickDryRun(dryRun):303 """304 Set the default value for optional dryRun parameter for iClick*305 functions.306 """307 global _g_defaultClickDryRun308 _g_defaultClickDryRun = dryRun309def iSetDefaultDelayedDrawing(delayedDrawing):310 """311 Set the default for delaying drawing operations on captured312 screenshots.313 If delayedDrawing == False, drawing actions on screenshots (like314 highlighting icon and clicked coordinates) takes place during the315 function execution (like iClickIcon).316 If delayedDrawing == True, the screenshot is saved without317 highlighted areas, and <screenshot filename>.delayeddraw file318 contains all draw commands that can be executed after the test319 run. This may save a lot test execution time and CPU on the device320 that runs eyenfinger.321 The default is False.322 """323 global _g_defaultDelayedDrawing324 _g_defaultDelayedDrawing = delayedDrawing325def iSetDefaultIconMatch(match):326 """327 Set the default icon matching value, ranging from 0 to 1. The328 value will be used in iClickIcon and iVerifyIcon, if the optional329 match parameter is omitted. Value 1.0 will use pixel-perfect330 matching (the default), values below 1.0 will use fuzzy matching.331 Fuzzy matching is EXPERIMENTAL.332 """333 global _g_defaultIconMatch334 _g_defaultIconMatch = match335def iSetDefaultIconColorMatch(colorMatch):336 """337 Set the default color matching value, ranging from 0 to 1. When338 using pixel-perfect matching this will allow given error in pixel339 colors.340 For instance, when comparing 24 bit RGB images, value 0.97 will341 allow 256 - int(256 * .97) = 8 difference on each color channel.342 """343 global _g_defaultIconColorMatch344 _g_defaultIconColorMatch = colorMatch345def iSetDefaultIconOpacityLimit(opacityLimit):346 """347 Set the default minimum opacity for pixels to be matched. Defaults348 to 0.0, all pixels are matched independently of their opacity.349 """350 global _g_defaultIconOpacityLimit351 _g_defaultIconOpacityLimit = opacityLimit352def iSetDefaultInputKeyDevice(deviceName):353 """354 Use deviceName as a default input device for iInputKey.355 iSetDefaultInputKeyDevice("/dev/input/event0")356 iInputKey(["enter"])357 """358 global _g_defaultInputKeyDevice359 _g_defaultInputKeyDevice = deviceName360def iSetDefaultReadWithOCR(ocr):361 """362 Set the default for using OCR when reading images or windows.363 """364 global _g_defaultReadWithOCR365 _g_defaultReadWithOCR = ocr366def screenSize():367 """368 Returns the size of the screen as a pair (width, height).369 """370 if _g_screenSize == (0, 0):371 _getScreenSize()372 return _g_screenSize373def windowSize():374 """375 Returns the size of the window as a pair (width, height).376 Choose a window first, for instance with iRead() or iUseWindow().377 """378 if _g_lastWindow == None:379 raise BadWindowName("undefined window")380 return _g_windowSizes[_g_lastWindow]381def windowXY():382 """383 Returns screen coordinates of the top-left corner of the window as384 a pair (x, y).385 Choose a window first, for instance with iRead() or iUseWindow().386 """387 if _g_lastWindow == None:388 raise BadWindowName("undefined window")389 return _g_windowOffsets[_g_lastWindow]390def imageSize(imageFilename):391 """392 Returns image size as pair (width, height).393 """394 struct_bbox = Bbox(0,0,0,0,0)395 err = eye4graphics.imageDimensions(ctypes.byref(struct_bbox),396 imageFilename)397 if err != 0:398 return None, None399 return struct_bbox.right, struct_bbox.bottom400def iRead(windowId = None, source = None, preprocess = None, ocr=None, capture=None, ocrArea=(0, 0, 1.0, 1.0), ocrPageSegModes=(3,), lang="eng", configfile=None):401 """402 DEPRECATED - use fmbtx11.Screen.refreshScreenshot instead.403 Read the contents of the given window or other source. If neither404 of windowId or source is given, reads the contents of active405 window. iClickWord and iVerifyWord can be used after reading with406 OCR.407 Parameters:408 windowId id (0x....) or the title of the window to be read.409 Defaults to None.410 source name of the file to be read, for instance a screen411 capture. Defaults to None.412 preprocess preprocess specification to override the default413 that is set using setPreprocessFilter. Defaults414 to None. Set to "" to disable preprocessing before415 OCR.416 ocr words will be read using OCR if True417 (the default). Read object can be used with418 iClickIcon and iVerifyIcon without OCR, too.419 capture save image with read words highlighted to this420 file. Default: None (nothing is saved).421 ocrArea (top, left, right, bottom) coordinates -422 area of the image to be read with OCR.423 ocrPageSegModes424 tuple of integers, see tesseract -pagesegmodes425 lang Tesseract language setting, the default is "eng".426 Refer to LANGUAGES in Tesseract documentation or427 man page.428 configfile Tesseract configuration file.429 Returns list of words detected by OCR from the read object.430 """431 global _g_hocr432 global _g_lastWindow433 global _g_words434 global _g_readImage435 global _g_origImage436 _g_words = None437 _g_readImage = None438 _g_origImage = None439 if ocr == None:440 ocr = _g_defaultReadWithOCR441 if not source:442 iUseWindow(windowId)443 # take a screenshot444 import fmbtx11445 fmbtx11.Screen().refreshScreenshot().save(SCREENSHOT_FILENAME + ".png")446 _runcmd("%s %s.png -crop %sx%s+%s+%s +repage '%s'" %447 (fmbt_config.imagemagick_convert, SCREENSHOT_FILENAME,448 _g_windowSizes[_g_lastWindow][0], _g_windowSizes[_g_lastWindow][1],449 _g_windowOffsets[_g_lastWindow][0], _g_windowOffsets[_g_lastWindow][1],450 SCREENSHOT_FILENAME))451 source = SCREENSHOT_FILENAME452 else:453 iUseImageAsWindow(source)454 _g_origImage = source455 orig_width, orig_height = _g_windowSizes[_g_lastWindow][0], _g_windowSizes[_g_lastWindow][1]456 x1, y1 = _coordsToInt(ocrArea[:2], (orig_width, orig_height))457 x2, y2 = _coordsToInt(ocrArea[2:], (orig_width, orig_height))458 if x2 <= x1 or y2 <= y1:459 raise EyenfingerError("Invalid area size: %s => %s" % (ocrArea, (x1, y1, x2, y2)))460 if orig_width <= 0 or orig_height <= 0:461 raise EyenfingerError("Invalid image size: %sx%s" % (orig_width, orig_height))462 if not ocr:463 if capture:464 drawWords(_g_origImage, capture, [], [])465 return []466 if preprocess == None:467 preprocess = _g_preprocess468 # convert to text469 _g_readImage = _g_origImage + "-pp.png"470 if ocrArea == (0, 0, 1.0, 1.0):471 croparea = []472 wordXOffset = 0473 wordYOffset = 0474 else:475 croparea = ["-crop", "%sx%s+%s+%s" % (x2-x1, y2-y1, x1, y1), "+repage"]476 wordXOffset = x1477 wordYOffset = y1478 # rescale possible resize preprocessing parameter479 resize_m = re.search('-resize ([0-9]+)x([0-9]*)', preprocess)480 if resize_m:481 origXResize = int(resize_m.group(1))482 newXResize = int(origXResize/float(orig_width) * (x2-x1))483 preprocess = (preprocess[:resize_m.start()] +484 ("-resize %sx" % (newXResize,)) +485 preprocess[resize_m.end():])486 _g_words = {}487 for psm in ocrPageSegModes:488 convert_cmd = ([fmbt_config.imagemagick_convert, _g_origImage] +489 croparea +490 shlex.split(preprocess) +491 [_g_readImage])492 tesseract_cmd = ["tesseract", _g_readImage, SCREENSHOT_FILENAME,493 "-l", lang, "-psm", str(psm), "hocr"]494 if isinstance(configfile, basestring):495 tesseract_cmd += [configfile]496 elif isinstance(configfile, list) or isinstance(configfile, tuple):497 tesseract_cmd += configfile498 exit_status, output = _runcmd(convert_cmd)499 if exit_status != 0:500 raise NoOCRResults("Convert returned exit status (%s): %s"501 % (exit_status, _g_last_runcmd_error))502 exit_status, output = _runcmd(tesseract_cmd)503 if exit_status != 0:504 raise NoOCRResults("Tesseract returned exit status (%s): %s"505 % (exit_status, _g_last_runcmd_error))506 hocr_filename = SCREENSHOT_FILENAME + ".html" # Tesseract 3.02507 if not os.access(hocr_filename, os.R_OK):508 hocr_filename = SCREENSHOT_FILENAME + ".hocr" # Tesseract 3.03509 if not os.access(hocr_filename, os.R_OK):510 raise NoOCRResults("HOCR output missing. Tesseract OCR 3.02 or greater required.\n")511 # store every word and its coordinates512 _g_words.update(_hocr2words(file(hocr_filename).read()))513 # convert word coordinates to the unscaled pixmap514 try:515 ocr_page_line = [line for line in file(hocr_filename).readlines() if "class='ocr_page'" in line][0]516 except IndexError:517 raise NoOCRResults("Could not read ocr_page class information from %s" % (hocr_filename,))518 scaled_width, scaled_height = re.findall('bbox 0 0 ([0-9]+)\s*([0-9]+)', ocr_page_line)[0]519 scaled_width, scaled_height = float(scaled_width) / (float(x2-x1)/orig_width), float(scaled_height) / (float(y2-y1)/orig_height)520 for word in sorted(_g_words.keys()):521 for appearance, (wordid, middle, bbox) in enumerate(_g_words[word]):522 _g_words[word][appearance] = \523 (wordid,524 (int(middle[0]/scaled_width * orig_width) + wordXOffset,525 int(middle[1]/scaled_height * orig_height) + wordYOffset),526 (int(bbox[0]/scaled_width * orig_width) + wordXOffset,527 int(bbox[1]/scaled_height * orig_height) + wordYOffset,528 int(bbox[2]/scaled_width * orig_width) + wordXOffset,529 int(bbox[3]/scaled_height * orig_height) + wordYOffset))530 _log('found "' + word + '": (' + str(bbox[0]) + ', ' + str(bbox[1]) + ')')531 if capture:532 drawWords(_g_origImage, capture, _g_words, _g_words)533 return sorted(_g_words.keys())534def iVerifyWord(word, match=0.33, appearance=1, capture=None):535 """536 DEPRECATED - use fmbtx11.Screen.verifyOcrText instead.537 Verify that word can be found from previously iRead() image.538 Parameters:539 word word that should be checked540 appearance if word appears many times, appearance to541 be clicked. Defaults to the first one.542 match minimum matching score543 capture save image with verified word highlighted544 to this file. Default: None (nothing is saved).545 Returns pair: ((score, matchingWord), (left, top, right, bottom)), where546 score score of found match (1.0 for perfect match)547 matchingWord corresponding word detected by OCR548 (left, top, right, bottom)549 bounding box of the word in read image550 Throws BadMatch error if word is not found.551 Throws NoOCRResults error if there are OCR results available552 on the current screen.553 """554 if _g_words == None:555 raise NoOCRResults('iRead has not been called with ocr=True')556 score, matching_word = findWord(word)557 if capture:558 drawWords(_g_origImage, capture, [word], _g_words)559 if score < match:560 raise BadMatch('No matching word for "%s". The best candidate "%s" with score %.2f, required %.2f' %561 (word, matching_word, score, match))562 return ((score, matching_word), _g_words[matching_word][appearance-1][2])563def iVerifyText(text, match=0.33, capture=None):564 """565 DEPRECATED - use fmbtx11.Screen.verifyOcrText instead.566 Verify that text can be found from previously iRead() image.567 Parameters:568 text multiple words that should be checked569 match minimum matching score570 capture save image with verified text highlighted571 to this file. Default: None (nothing is saved).572 Returns pair:573 ((score, matchingText), (left, top, right, bottom)), where574 score score of found match (1.0 for perfect match)575 matchingText corresponding text detected by OCR576 (left, top, right, bottom)577 bounding box of the text in read image578 Throws BadMatch error if text is not found.579 Throws NoOCRResults error if there are OCR results available580 on the current screen.581 """582 if _g_words == None:583 raise NoOCRResults('iRead has not been called with ocr=True')584 score_text_bbox_list = findText(text, match)585 if len(score_text_bbox_list) == 0:586 raise BadMatch('No match >= %s for text "%s"' % (score, text))587 score, text, bbox = score_text_box_list[0]588 if capture:589 drawBbox(_g_origImage, capture, bbox, "%.2f %s" % (score, text))590 return ((score, matching_text), bbox)591def iVerifyIcon(iconFilename, match=None, colorMatch=None, opacityLimit=None, capture=None, area=(0.0, 0.0, 1.0, 1.0), _origin="iVerifyIcon"):592 """593 DEPRECATED - use fmbtx11.Screen.verifyBitmap instead.594 Verify that icon can be found from previously iRead() image.595 Parameters:596 iconFilename name of the icon file to be searched for597 match minimum matching score between 0 and 1.0,598 1.0 is perfect match (default)599 colorMatch 1.0 (default) requires exact color match. Value600 below 1.0 defines maximum allowed color601 difference. See iSetDefaultIconColorMatch.602 opacityLimit 0.0 (default) requires exact color values603 independently of opacity. If lower than 1.0,604 pixel less opaque than given value are skipped605 in pixel perfect comparisons.606 capture save image with verified icon highlighted607 to this file. Default: None (nothing is saved).608 area rectangle (left, top, right, bottom). Search609 icon inside this rectangle only. Values can be610 absolute coordinates, or floats in range [0.0,611 1.0] that will be scaled to image dimensions.612 The default is (0.0, 0.0, 1.0, 1.0), that is613 full rectangle.614 Returns pair: (score, (left, top, right, bottom)), where615 score score of found match (1.0 for perfect match)616 (left, top, right, bottom)617 bounding box of found icon618 Throws BadMatch error if icon is not found.619 """620 if not eye4graphics:621 _log('ERROR: %s("%s") called, but eye4graphics not loaded.' % (_origin, iconFilename))622 raise EyenfingerError("eye4graphics not available")623 if not _g_origImage:624 _log('ERROR %s("%s") called, but source not defined (iRead not called).' % (_origin, iconFilename))625 raise BadSourceImage("Source image not defined, cannot search for an icon.")626 if not (os.path.isfile(iconFilename) and os.access(iconFilename, os.R_OK)):627 _log('ERROR %s("%s") called, but the icon file is not readable.' % (_origin, iconFilename))628 raise BadIconImage('Icon "%s" is not readable.' % (iconFilename,))629 if match == None:630 match = _g_defaultIconMatch631 if match > 1.0:632 _log('ERROR %s("%s"): invalid match value, must be below 1.0. ' % (_origin, iconFilename,))633 raise ValueError("invalid match value: %s, should be 0 <= match <= 1.0" % (match,))634 if colorMatch == None:635 colorMatch = _g_defaultIconColorMatch636 if not 0.0 <= colorMatch <= 1.0:637 _log('ERROR %s("%s"): invalid colorMatch value, must be between 0 and 1. ' % (_origin, iconFilename,))638 raise ValueError("invalid colorMatch value: %s, should be 0 <= colorMatch <= 1.0" % (colorMatch,))639 if opacityLimit == None:640 opacityLimit = _g_defaultIconOpacityLimit641 if not 0.0 <= opacityLimit <= 1.0:642 _log('ERROR %s("%s"): invalid opacityLimit value, must be between 0 and 1. ' % (_origin, iconFilename,))643 raise ValueError("invalid opacityLimit value: %s, should be 0 <= opacityLimit <= 1.0" % (opacityLimit,))644 if area[0] > area[2] or area[1] >= area[3]:645 raise ValueError("invalid area: %s, should be rectangle (left, top, right, bottom)" % (area,))646 leftTopRightBottomZero = (_coordsToInt((area[0], area[1]), windowSize()) +647 _coordsToInt((area[2], area[3]), windowSize()) +648 (0,))649 struct_area_bbox = Bbox(*leftTopRightBottomZero)650 struct_bbox = Bbox(0,0,0,0,0)651 threshold = int((1.0-match)*20)652 err = eye4graphics.findSingleIcon(ctypes.byref(struct_bbox),653 _g_origImage, iconFilename, threshold,654 ctypes.c_double(colorMatch),655 ctypes.c_double(opacityLimit),656 ctypes.byref(struct_area_bbox))657 bbox = (int(struct_bbox.left), int(struct_bbox.top),658 int(struct_bbox.right), int(struct_bbox.bottom))659 if err == -1 or err == -2:660 msg = '%s: "%s" not found, match=%.2f, threshold=%s, closest threshold %s.' % (661 _origin, iconFilename, match, threshold, int(struct_bbox.error))662 if capture:663 drawIcon(_g_origImage, capture, iconFilename, bbox, 'red')664 _log(msg)665 raise BadMatch(msg)666 elif err != 0:667 _log("%s: findSingleIcon returned %s" % (_origin, err,))668 raise BadMatch("%s not found, findSingleIcon returned %s." % (iconFilename, err))669 if threshold > 0:670 score = (threshold - int(struct_bbox.error)) / float(threshold)671 else:672 score = 1.0673 if capture:674 drawIcon(_g_origImage, capture, iconFilename, bbox, area=leftTopRightBottomZero[:4])675 return (score, bbox)676def iClickIcon(iconFilename, clickPos=(0.5,0.5), match=None,677 colorMatch=None, opacityLimit=None,678 mouseButton=1, mouseEvent=MOUSEEVENT_CLICK, dryRun=None, capture=None):679 """680 DEPRECATED - use fmbtx11.Screen.tapBitmap instead.681 Click coordinates relative to the given icon in previously iRead() image.682 Parameters:683 iconFilename read icon from this file684 clickPos position to be clicked,685 relative to word top-left corner of the bounding686 box around the word. X and Y units are relative687 to width and height of the box. (0,0) is the688 top-left corner, (1,1) is bottom-right corner,689 (0.5, 0.5) is the middle point (default).690 Values below 0 or greater than 1 click outside691 the bounding box.692 match 1.0 (default) requires exact match. Value below 1.0693 defines minimum required score for fuzzy matching694 (EXPERIMENTAL). See iSetDefaultIconMatch.695 colorMatch 1.0 (default) requires exact color match. Value696 below 1.0 defines maximum allowed color697 difference. See iSetDefaultIconColorMatch.698 opacityLimit 0.0 (default) requires exact color values699 independently of opacity. If lower than 1.0,700 pixel less opaque than given value are skipped701 in pixel perfect comparisons.702 mouseButton mouse button to be synthesized on the event, default is 1.703 mouseEvent event to be synthesized, the default is MOUSEEVENT_CLICK,704 others: MOUSEEVENT_MOVE, MOUSEEVENT_DOWN, MOUSEEVENT_UP.705 dryRun if True, does not synthesize events. Still returns706 coordinates of the clicked position and illustrates707 the clicked position on the capture image if708 given.709 capture name of file where image of highlighted icon and710 clicked point are saved.711 Returns pair (score, (clickedX, clickedY)), where712 score score of found match (1.0 for perfect match)713 (clickedX, clickedY)714 X and Y coordinates of clicked position on the715 screen.716 Throws BadMatch error if could not find a matching word.717 """718 _DEPRECATED()719 score, bbox = iVerifyIcon(iconFilename, match=match,720 colorMatch=colorMatch, opacityLimit=opacityLimit,721 capture=capture, _origin="iClickIcon")722 clickedXY = iClickBox(bbox, clickPos, mouseButton, mouseEvent, dryRun,723 capture, _captureText = iconFilename)724 return (score, clickedXY)725def iClickWord(word, appearance=1, clickPos=(0.5,0.5), match=0.33,726 mouseButton=1, mouseEvent=1, dryRun=None, capture=None):727 """728 DEPRECATED - use fmbtx11.Screen.tapOcrText instead.729 Click coordinates relative to the given word in previously iRead() image.730 Parameters:731 word word that should be clicked732 appearance if word appears many times, appearance to733 be clicked. Defaults to the first one.734 clickPos position to be clicked,735 relative to word top-left corner of the bounding736 box around the word. X and Y units are relative737 to width and height of the box. (0,0) is the738 top-left corner, (1,1) is bottom-right corner,739 (0.5, 0.5) is the middle point (default).740 Values below 0 or greater than 1 click outside741 the bounding box.742 capture name of file where image of highlighted word and743 clicked point are saved.744 Returns pair: ((score, matchingWord), (clickedX, clickedY)), where745 score score of found match (1.0 for perfect match)746 matchingWord corresponding word detected by OCR747 (clickedX, clickedY)748 X and Y coordinates of clicked position on the749 screen.750 Throws BadMatch error if could not find a matching word.751 Throws NoOCRResults error if there are OCR results available752 on the current screen.753 """754 _DEPRECATED()755 (score, matching_word), bbox = iVerifyWord(word, appearance=appearance, match=match, capture=False)756 clickedX, clickedY = iClickBox(bbox, clickPos, mouseButton, mouseEvent, dryRun, capture=False)757 windowId = _g_lastWindow758 _log('iClickWord("%s"): word "%s", match %.2f, bbox %s, window offset %s, click %s' %759 (word, matching_word, score,760 bbox, _g_windowOffsets[windowId],761 (clickedX, clickedY)))762 if capture:763 drawWords(_g_origImage, capture, [word], _g_words)764 drawClickedPoint(capture, capture, (clickedX, clickedY))765 return ((score, matching_word), (clickedX, clickedY))766def iClickBox((left, top, right, bottom), clickPos=(0.5, 0.5),767 mouseButton=1, mouseEvent=1, dryRun=None,768 capture=None, _captureText=None):769 """770 DEPRECATED - use fmbtx11.Screen.tapItem instead.771 Click coordinates relative to the given bounding box, default is772 in the middle of the box.773 Parameters:774 (left, top, right, bottom)775 coordinates of the box inside the window.776 (0, 0) is the top-left corner of the window.777 clickPos (offsetX, offsetY) position to be clicked,778 relative to the given box. (0, 0) is the779 top-left, and (1.0, 1.0) is the lower-right780 corner of the box. The default is (0.5, 0.5),781 that is, the middle point of the box. Values782 smaller than 0 and bigger than 1 are allowed,783 too.784 mouseButton mouse button to be synthesized on the event, default is 1.785 mouseEvent event to be synthesized, the default is MOUSEEVENT_CLICK,786 others: MOUSEEVENT_MOVE, MOUSEEVENT_DOWN, MOUSEEVENT_UP.787 dryRun if True, does not synthesize events. Still returns788 coordinates of the clicked position and illustrates789 the clicked position on the capture image if790 given.791 capture name of file where the last screenshot with792 clicked point highlighted is saved. The default793 is None (nothing is saved).794 Returns pair (clickedX, clickedY)795 X and Y coordinates of clicked position on the796 screen.797 """798 clickWinX = int(left + clickPos[0]*(right-left))799 clickWinY = int(top + clickPos[1]*(bottom-top))800 (clickedX, clickedY) = iClickWindow((clickWinX, clickWinY),801 mouseButton, mouseEvent,802 dryRun, capture=False)803 if capture:804 if _captureText == None:805 _captureText = "Box: %s, %s, %s, %s" % (left, top, right, bottom)806 drawIcon(_g_origImage, capture, _captureText, (left, top, right, bottom))807 drawClickedPoint(capture, capture, (clickedX, clickedY))808 return (clickedX, clickedY)809def iClickWindow((clickX, clickY), mouseButton=1, mouseEvent=1, dryRun=None, capture=None):810 """811 DEPRECATED - use fmbtx11.Screen.tap instead.812 Click given coordinates in the window.813 Parameters:814 (clickX, clickY)815 coordinates to be clicked inside the window.816 (0, 0) is the top-left corner of the window.817 Integer values are window coordinates. Floating818 point values from 0.0 to 1.0 are scaled to window819 coordinates: (0.5, 0.5) is the middle of the820 window, and (1.0, 1.0) the bottom-right corner of821 the window.822 mouseButton mouse button to be synthesized on the event, default is 1.823 mouseEvent event to be synthesized, the default is MOUSEEVENT_CLICK,824 others: MOUSEEVENT_MOVE, MOUSEEVENT_DOWN, MOUSEEVENT_UP.825 dryRun if True, does not synthesize events. Still826 illustrates the clicked position on the capture827 image if given.828 capture name of file where the last screenshot with829 clicked point highlighted is saved. The default830 is None (nothing is saved).831 Returns pair (clickedX, clickedY)832 X and Y coordinates of clicked position on the833 screen.834 """835 # Get the size of the window836 wndSize = windowSize()837 (clickX, clickY) = _coordsToInt((clickX, clickY), wndSize)838 # Get the position of the window839 wndPos = windowXY()840 # If coordinates are given as percentages, convert to window coordinates841 clickScrX = clickX + wndPos[0]842 clickScrY = clickY + wndPos[1]843 iClickScreen((clickScrX, clickScrY), mouseButton, mouseEvent, dryRun, capture)844 return (clickScrX, clickScrY)845def iClickScreen((clickX, clickY), mouseButton=1, mouseEvent=1, dryRun=None, capture=None):846 """847 DEPRECATED - use fmbtx11.Screen.tap instead.848 Click given absolute coordinates on the screen.849 Parameters:850 (clickX, clickY)851 coordinates to be clicked on the screen. (0, 0)852 is the top-left corner of the screen. Integer853 values are screen coordinates. Floating point854 values from 0.0 to 1.0 are scaled to screen855 coordinates: (0.5, 0.5) is the middle of the856 screen, and (1.0, 1.0) the bottom-right corner of857 the screen.858 mouseButton mouse button to be synthesized on the event, default is 1.859 mouseEvent event to be synthesized, the default is MOUSEEVENT_CLICK,860 others: MOUSEEVENT_MOVE, MOUSEEVENT_DOWN, MOUSEEVENT_UP.861 dryRun if True, does not synthesize events. Still862 illustrates the clicked position on the capture863 image if given.864 capture name of file where the last screenshot with865 clicked point highlighted is saved. The default866 is None (nothing is saved).867 """868 _DEPRECATED()869 if mouseEvent == MOUSEEVENT_CLICK:870 params = "'mouseclick %s'" % (mouseButton,)871 elif mouseEvent == MOUSEEVENT_DOWN:872 params = "'mousedown %s'" % (mouseButton,)873 elif mouseEvent == MOUSEEVENT_UP:874 params = "'mouseup %s'" % (mouseButton,)875 else:876 params = ""877 clickX, clickY = _coordsToInt((clickX, clickY))878 if capture:879 drawClickedPoint(_g_origImage, capture, (clickX, clickY))880 if dryRun == None:881 dryRun = _g_defaultClickDryRun882 if not dryRun:883 # use xte from the xautomation package884 _runcmd("xte 'mousemove %s %s' %s" % (clickX, clickY, params))885def iGestureScreen(listOfCoordinates, duration=0.5, holdBeforeGesture=0.0, holdAfterGesture=0.0, intermediatePoints=0, capture=None, dryRun=None):886 """887 DEPRECATED - use fmbtx11.Screen.drag instead.888 Synthesizes a gesture on the screen.889 Parameters:890 listOfCoordinates891 The coordinates through which the cursor moves.892 Integer values are screen coordinates. Floating893 point values from 0.0 to 1.0 are scaled to screen894 coordinates: (0.5, 0.5) is the middle of the895 screen, and (1.0, 1.0) the bottom-right corner of896 the screen.897 duration gesture time in seconds, excluding898 holdBeforeGesture and holdAfterGesture times.899 holdBeforeGesture900 time in seconds to keep mouse down before the901 gesture.902 holdAfterGesture903 time in seconds to keep mouse down after the904 gesture.905 intermediatePoints906 the number of intermediate points to be added907 between each of the coordinates. Intermediate908 points are added to straight lines between start909 and end points.910 capture name of file where the last screenshot with911 the points through which the cursors passes is912 saved. The default is None (nothing is saved).913 dryRun if True, does not synthesize events. Still914 illustrates the coordinates through which the cursor915 goes.916 """917 _DEPRECATED()918 # The params list to be fed to xte919 params = []920 # The list of coordinates through which the cursor has to go921 goThroughCoordinates = []922 for pos in xrange(len(listOfCoordinates)):923 x, y = _coordsToInt(listOfCoordinates[pos])924 goThroughCoordinates.append((x,y))925 if pos == len(listOfCoordinates) - 1:926 break # last coordinate added927 nextX, nextY = _coordsToInt(listOfCoordinates[pos+1])928 (x,y), (nextX, nextY) = (x, y), (nextX, nextY)929 for ip in range(intermediatePoints):930 goThroughCoordinates.append(931 (int(round(x + (nextX-x)*(ip+1)/float(intermediatePoints+1))),932 int(round(y + (nextY-y)*(ip+1)/float(intermediatePoints+1)))))933 # Calculate the time (in micro seconds) to sleep between moves.934 if len(goThroughCoordinates) > 1:935 moveDelay = 1000000 * float(duration) / (len(goThroughCoordinates)-1)936 else:937 moveDelay = 0938 if not dryRun:939 # Build the params list.940 params.append("'mousemove %d %d'" % goThroughCoordinates[0])941 params.append("'mousedown 1 '")942 if holdBeforeGesture > 0:943 params.append("'usleep %d'" % (holdBeforeGesture * 1000000,))944 for i in xrange(1, len(goThroughCoordinates)):945 params.append("'usleep %d'" % (moveDelay,))946 params.append("'mousemove %d %d'" % goThroughCoordinates[i])947 if holdAfterGesture > 0:948 params.append("'usleep %d'" % (holdAfterGesture * 1000000,))949 params.append("'mouseup 1'")950 # Perform the gesture951 _runcmd("xte %s" % (" ".join(params),))952 if capture:953 intCoordinates = [ _coordsToInt(point) for point in listOfCoordinates ]954 drawLines(_g_origImage, capture, intCoordinates, goThroughCoordinates)955 return goThroughCoordinates956def iGestureWindow(listOfCoordinates, duration=0.5, holdBeforeGesture=0.0, holdAfterGesture=0.0, intermediatePoints=0, capture=None, dryRun=None):957 """958 DEPRECATED - use fmbtx11.Screen.drag instead.959 Synthesizes a gesture on the window.960 Parameters:961 listOfCoordinates962 The coordinates through which the cursor moves.963 Integer values are window coordinates. Floating964 point values from 0.0 to 1.0 are scaled to window965 coordinates: (0.5, 0.5) is the middle of the966 window, and (1.0, 1.0) the bottom-right corner of967 the window.968 duration gesture time in seconds, excluding969 holdBeforeGesture and holdAfterGesture times.970 holdBeforeGesture971 time in seconds to keep mouse down before the972 gesture.973 holdAfterGesture974 time in seconds to keep mouse down after the975 gesture.976 intermediatePoints977 the number of intermediate points to be added978 between each of the coordinates. Intermediate979 points are added to straight lines between start980 and end points.981 capture name of file where the last screenshot with982 the points through which the cursors passes is983 saved. The default is None (nothing is saved).984 dryRun if True, does not synthesize events. Still985 illustrates the coordinates through which the cursor986 goes.987 """988 screenCoordinates = [ _windowToScreen(*_coordsToInt((x,y),windowSize())) for (x,y) in listOfCoordinates ]989 return iGestureScreen(screenCoordinates, duration, holdBeforeGesture, holdAfterGesture, intermediatePoints, capture, dryRun)990def iType(word, delay=0.0):991 """992 DEPRECATED - use fmbtx11.Screen.type instead.993 Send keypress events.994 Parameters:995 word is either996 - a string containing letters and numbers.997 Each letter/number is using press and release events.998 - a list that contains999 - keys: each key is sent using press and release events.1000 - (key, event)-pairs: the event (either "press" or "release")1001 is sent.1002 - (key1, key2, ..., keyn)-tuples. 2n events is sent:1003 key1 press, key2 press, ..., keyn press,1004 keyn release, ..., key2 release, key1 release.1005 Keys are defined in eyenfinger.Xkeys, for complete list1006 see keysymdef.h.1007 delay is given as seconds between sent events1008 Examples:1009 iType('hello')1010 iType([('Shift_L', 'press'), 'h', 'e', ('Shift_L', 'release'), 'l', 'l', 'o'])1011 iType([('Control_L', 'Alt_L', 'Delete')])1012 """1013 _DEPRECATED()1014 args = []1015 for char in word:1016 if type(char) == tuple:1017 if char[1].lower() == 'press':1018 args.append("'keydown %s'" % (char[0],))1019 elif char[1].lower() == 'release':1020 args.append("'keyup %s'" % (char[0],))1021 else:1022 rest = []1023 for key in char:1024 args.append("'keydown %s'" % (key,))1025 rest.insert(0, "'keyup %s'" % (key,))1026 args = args + rest1027 else:1028 # char is keyname or single letter/number1029 args.append("'key %s'" % (char,))1030 usdelay = " 'usleep %s' " % (int(delay*1000000),)1031 _runcmd("xte %s" % (usdelay.join(args),))1032def iInputKey(*args, **kwargs):1033 """1034 DEPRECATED - use fmbtx11.Screen.pressKey instead.1035 Send keypresses using Linux evdev interface1036 (/dev/input/eventXX).1037 iInputKey(keySpec[, keySpec...], hold=<float>, delay=<float>, device=<str>)1038 Parameters:1039 keySpec is one of the following:1040 - a string of one-character-long key names:1041 "aesc" will send four keypresses: A, E, S and C.1042 - a list of key names:1043 ["a", "esc"] will send two keypresses: A and ESC.1044 Key names are listed in eyenfinger.InputKeys.1045 - an integer:1046 116 will press the POWER key.1047 - "_" or "^":1048 only press or release event will be generated1049 for the next key, respectively.1050 If a key name inside keySpec is prefixed by "_"1051 or "^", only press or release event is generated1052 for that key.1053 hold time (in seconds) to hold the key before1054 releasing. The default is 0.1.1055 delay delay (in seconds) after key release. The default1056 is 0.1.1057 device name of the input device or input event file to1058 which all key presses are sent. The default can1059 be set with iSetDefaultInputKeyDevice(). For1060 instance, "/dev/input/event0" or a name of a1061 device in /proc/bus/input/devices.1062 """1063 _DEPRECATED()1064 hold = kwargs.get("hold", 0.1)1065 delay = kwargs.get("delay", 0.1)1066 device = kwargs.get("device", _g_defaultInputKeyDevice)1067 inputKeySeq = []1068 press, release = 1, 11069 for a in args:1070 if a == "_": press, release = 1, 01071 elif a == "^": press, release = 0, 11072 elif type(a) == str:1073 for char in a:1074 if char == "_": press, release = 1, 01075 elif char == "^": press, release = 0, 11076 else:1077 inputKeySeq.append((press, release, _inputKeyNameToCode(char.upper())))1078 press, release = 1, 11079 elif type(a) in (tuple, list):1080 for keySpec in a:1081 if type(keySpec) == int:1082 inputKeySeq.append((press, release, keySpec))1083 press, release = 1, 11084 else:1085 if keySpec.startswith("_"):1086 press, release = 1, 01087 keySpec = keySpec[1:]1088 elif keySpec.startswith("^"):1089 press, release = 0, 11090 keySpec = keySpec[1:]1091 if keySpec:1092 inputKeySeq.append((press, release, _inputKeyNameToCode(keySpec.upper())))1093 press, release = 1, 11094 elif type(a) == int:1095 inputKeySeq.append((press, release, a))1096 press, release = 1, 11097 else:1098 raise ValueError('Invalid keySpec "%s"' % (a,))1099 if inputKeySeq:1100 _writeInputKeySeq(_deviceFilename(device), inputKeySeq, hold=hold, delay=delay)1101def _deviceFilename(deviceName):1102 if not _deviceFilename.deviceCache:1103 _deviceFilename.deviceCache = dict(_listInputDevices())1104 if not deviceName in _deviceFilename.deviceCache:1105 return deviceName1106 else:...
fmbttizen-agent.py
Source:fmbttizen-agent.py
1# fMBT, free Model Based Testing tool2# Copyright (c) 2013, Intel Corporation.3#4# This program is free software; you can redistribute it and/or modify it5# under the terms and conditions of the GNU Lesser General Public License,6# version 2.1, as published by the Free Software Foundation.7#8# This program is distributed in the hope it will be useful, but WITHOUT9# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for11# more details.12#13# You should have received a copy of the GNU Lesser General Public License along with14# this program; if not, write to the Free Software Foundation, Inc.,15# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.16import base6417import cPickle18import ctypes19import fcntl20import glob21import os22import platform23import re24import shlex25import shutil26import string27import struct28import subprocess29import sys30import termios31import time32import zlib33import fmbtuinput34fmbtuinput.refreshDeviceInfo()35if "--debug" in sys.argv:36 g_debug = True37else:38 g_debug = False39try:40 _opt_keyboard = [a.split("=")[1] for a in sys.argv if a.startswith("--keyboard=")][0]41except IndexError:42 _opt_keyboard = None43try:44 _opt_touch = [a.split("=")[1] for a in sys.argv if a.startswith("--touch=")][0]45except IndexError:46 _opt_touch = None47try:48 _opt_mouse = [a.split("=")[1] for a in sys.argv if a.startswith("--mouse=")][0]49except IndexError:50 _opt_mouse = None51keyboard_device = None52touch_device = None53mouse_device = None54def openKeyboardDevice(keyboardSpec=None):55 keyboard_device = None56 if keyboardSpec == None:57 try:58 keyboard_device = openKeyboardDevice("sysrq")59 except IndexError:60 keyboard_device = openKeyboardDevice("virtual")61 elif keyboardSpec in (None, "virtual"):62 keyboard_device = fmbtuinput.Keyboard().create()63 elif keyboardSpec.startswith("file:"):64 keyboard_device = fmbtuinput.Keyboard().open(keyboardSpec.split(":",1)[1])65 elif keyboardSpec == "sysrq":66 keyboard_device = fmbtuinput.Keyboard().open(67 "/dev/input/" + re.findall(68 '[ =](event[0-9]+)\s',69 [i for i in devices.split("\n\n") if "sysrq" in i.lower()][0])[0])70 elif keyboardSpec == "disabled":71 keyboard_device = None72 return keyboard_device73def openTouchDevice(touchSpec=None, fallback=None):74 touch_device = None75 if touchSpec == None:76 if fallback != None:77 return openTouchDevice(fallback)78 else:79 pass # will return None80 elif touchSpec.startswith("virtual"):81 inputResolution=re.findall("virtual:([0-9]*)x([0-9]*)", touchSpec)82 if inputResolution:83 maxX = int(inputResolution[0][0])84 maxY = int(inputResolution[0][1])85 else:86 maxX, maxY = None, None87 touch_device = fmbtuinput.Touch().create(maxX=maxX, maxY=maxY)88 elif touchSpec.startswith("file:") or touchSpec.startswith("name:"):89 touch_device = fmbtuinput.Touch().open(touchSpec.split(":",1)[1])90 elif touchSpec == "disabled":91 pass # will return None92 else:93 raise ValueError('invalid touch device "%s"' % (touchSpec,))94 return touch_device95def openMouseDevice(mouseSpec=None, fallback=None):96 mouse_device = None97 if mouseSpec == None:98 if fallback != None:99 return openMouseDevice(fallback)100 else:101 pass # will return None102 elif mouseSpec.startswith("virtual:"):103 abs_or_rel = mouseSpec.split(":",1)[1]104 if abs_or_rel == "abs":105 absoluteMove = True106 elif abs_or_rel == "rel":107 absoluteMove = False108 else:109 raise ValueError('invalid mouse "%s"' % (mouseSpec,))110 mouse_device = fmbtuinput.Mouse(absoluteMove=absoluteMove).create()111 elif mouseSpec.startswith("file:") or mouseSpec.startswith("name:"):112 mouse_device = fmbtuinput.Mouse().open(mouseSpec.split(":",1)[1])113 elif mouseSpec == "disabled":114 pass # will return None115 else:116 raise ValueError('invalid mouse device "%s"' % (mouseSpec,))117 return mouse_device118def debug(msg):119 if g_debug:120 sys.stdout.write("debug: %s\n" % (msg,))121 sys.stdout.flush()122def error(msg, exitstatus=1):123 sys.stdout.write("fmbttizen-agent: %s\n" % (msg,))124 sys.stdout.flush()125 sys.exit(exitstatus)126iAmRoot = (os.getuid() == 0)127try:128 libc = ctypes.CDLL("libc.so.6")129 libX11 = ctypes.CDLL("libX11.so.6")130 libXtst = ctypes.CDLL("libXtst.so.6")131 g_Xavailable = True132 g_keyb = None # no need for virtual keyboard133except OSError:134 g_Xavailable = False135if g_Xavailable:136 class XImage(ctypes.Structure):137 _fields_ = [138 ('width' , ctypes.c_int),139 ('height' , ctypes.c_int),140 ('xoffset' , ctypes.c_int),141 ('format' , ctypes.c_int),142 ('data' , ctypes.c_void_p),143 ('byte_order' , ctypes.c_int),144 ('bitmap_unit' , ctypes.c_int),145 ('bitmap_bit_order' , ctypes.c_int),146 ('bitmap_pad' , ctypes.c_int),147 ('depth' , ctypes.c_int),148 ('bytes_per_line' , ctypes.c_int),149 ('bits_per_pixel' , ctypes.c_int)]150 libc.write.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_size_t]151 libX11.XAllPlanes.restype = ctypes.c_ulong152 libX11.XGetImage.restype = ctypes.POINTER(XImage)153 libX11.XRootWindow.restype = ctypes.c_uint32154 libX11.XOpenDisplay.restype = ctypes.c_void_p155 libX11.XDefaultScreen.restype = ctypes.c_int156 libX11.XGetKeyboardMapping.restype = ctypes.POINTER(ctypes.c_uint32)157 # X11 constants, see Xlib.h158 X_CurrentTime = ctypes.c_ulong(0)159 X_False = ctypes.c_int(0)160 X_NULL = ctypes.c_void_p(0)161 X_True = ctypes.c_int(1)162 X_ZPixmap = ctypes.c_int(2)163 NoSymbol = 0164# InputKeys contains key names known to input devices, see165# linux/input.h or http://www.usb.org/developers/hidpage. The order is166# significant, because keyCode = InputKeys.index(keyName).167InputKeys = [168 "RESERVED", "ESC","1", "2", "3", "4", "5", "6", "7", "8", "9", "0",169 "MINUS", "EQUAL", "BACKSPACE", "TAB",170 "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",171 "LEFTBRACE", "RIGHTBRACE", "ENTER", "LEFTCTRL",172 "A", "S", "D", "F", "G", "H", "J", "K", "L",173 "SEMICOLON", "APOSTROPHE", "GRAVE", "LEFTSHIFT", "BACKSLASH",174 "Z", "X", "C", "V", "B", "N", "M",175 "COMMA", "DOT", "SLASH", "RIGHTSHIFT", "KPASTERISK", "LEFTALT",176 "SPACE", "CAPSLOCK",177 "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",178 "NUMLOCK", "SCROLLLOCK",179 "KP7", "KP8", "KP9", "KPMINUS",180 "KP4", "KP5", "KP6", "KPPLUS",181 "KP1", "KP2", "KP3", "KP0", "KPDOT",182 "undefined0",183 "ZENKAKUHANKAKU", "102ND", "F11", "F12", "RO",184 "KATAKANA", "HIRAGANA", "HENKAN", "KATAKANAHIRAGANA", "MUHENKAN",185 "KPJPCOMMA", "KPENTER", "RIGHTCTRL", "KPSLASH", "SYSRQ", "RIGHTALT",186 "LINEFEED", "HOME", "UP", "PAGEUP", "LEFT", "RIGHT", "END", "DOWN",187 "PAGEDOWN", "INSERT", "DELETE", "MACRO",188 "MUTE", "VOLUMEDOWN", "VOLUMEUP",189 "POWER",190 "KPEQUAL", "KPPLUSMINUS", "PAUSE", "SCALE", "KPCOMMA", "HANGEUL",191 "HANGUEL", "HANJA", "YEN", "LEFTMETA", "RIGHTMETA", "COMPOSE"]192_inputKeyNameToCode={}193for c, n in enumerate(InputKeys):194 _inputKeyNameToCode[n] = c195# See struct input_event in /usr/include/linux/input.h196if platform.architecture()[0] == "32bit": _input_event = 'IIHHi'197else: _input_event = 'QQHHi'198# Event and keycodes are in input.h, too.199_EV_KEY = 0x01200_EV_ABS = 0x03201_ABS_X = 0x00202_ABS_Y = 0x01203_ABS_MT_SLOT = 0x2f204_ABS_MT_POSITION_X = 0x35205_ABS_MT_POSITION_Y = 0x36206_ABS_MT_TRACKING_ID = 0x39207_BTN_MOUSE = 0x110208# Set input device names (in /proc/bus/input/devices)209# for pressing hardware keys.210try: cpuinfo = file("/proc/cpuinfo").read()211except: cpuinfo = ""212def readDeviceInfo():213 global devices214 try:215 devices = file("/proc/bus/input/devices").read()216 except:217 devices = ""218readDeviceInfo()219kbInputDevFd = None220if ('max77803-muic' in devices or221 'max77804k-muic' in devices):222 debug("detected max77803-muic or max77804k-muic")223 hwKeyDevice = {224 "POWER": "qpnp_pon",225 "VOLUMEUP": "gpio-keys",226 "VOLUMEDOWN": "gpio-keys",227 "HOME": "gpio-keys",228 "BACK": "sec_touchkey",229 "MENU": "sec_touchkey"230 }231 _inputKeyNameToCode["HOME"] = 139 # KEY_MENU232 _inputKeyNameToCode["MENU"] = 169 # KEY_PHONE233 if iAmRoot:234 touch_device = openTouchDevice(_opt_touch, "name:sec_touchscreen")235elif 'max77693-muic' in devices:236 debug("detected max77693-muic")237 hwKeyDevice = {238 "POWER": "gpio-keys",239 "VOLUMEUP": "gpio-keys",240 "VOLUMEDOWN": "gpio-keys",241 "HOME": "gpio-keys",242 "MENU": "gpio-keys",243 }244 _inputKeyNameToCode["HOME"] = 139245 if iAmRoot:246 touch_device = openTouchDevice(_opt_touch, "name:sec_touchscreen")247elif 'TRATS' in cpuinfo:248 debug("detected TRATS")249 # Running on Lunchbox250 hwKeyDevice = {251 "POWER": "gpio-keys",252 "VOLUMEUP": "gpio-keys",253 "VOLUMEDOWN": "gpio-keys",254 "HOME": "gpio-keys"255 }256 _inputKeyNameToCode["HOME"] = 139257 if iAmRoot:258 touch_device = openTouchDevice(_opt_touch, "file:/dev/input/event2")259elif 'QEMU Virtual CPU' in cpuinfo:260 debug("detected QEMU Virtual CPU")261 if "Maru Virtio Hwkey" in devices:262 _hwkeydev = "Maru Virtio Hwkey" # Tizen 2.3b emulator263 else:264 _hwkeydev = "AT Translated Set 2 hardkeys"265 # Running on Tizen emulator266 hwKeyDevice = {267 "POWER": "Power Button",268 "VOLUMEUP": _hwkeydev,269 "VOLUMEDOWN": _hwkeydev,270 "HOME": _hwkeydev,271 "BACK": _hwkeydev,272 "MENU": _hwkeydev273 }274 del _hwkeydev275 _inputKeyNameToCode["HOME"] = 139276 _inputKeyNameToCode["MENU"] = 169 # KEY_PHONE277 if iAmRoot:278 touch_device = openTouchDevice(_opt_touch, "file:/dev/input/event2")279elif 'Synaptics_RMI4_touchkey' in devices:280 debug("detected Synaptics_RMI4_touchkey")281 # Running on Geek282 hwKeyDevice = {283 "POWER": "mid_powerbtn",284 "VOLUMEUP": "gpio-keys",285 "VOLUMEDOWN": "gpio-keys",286 "HOME": "Synaptics_RMI4_touchkey",287 "BACK": "Synaptics_RMI4_touchkey",288 "MENU": "Synaptics_RMI4_touchkey"289 }290 if iAmRoot:291 touch_device = openTouchDevice(_opt_touch, "file:/dev/input/event1")292elif 'mxt224_key_0' in devices:293 debug("detected mxt225_key_0")294 # Running on Blackbay295 hwKeyDevice = {296 "POWER": "msic_power_btn",297 "VOLUMEUP": "gpio-keys",298 "VOLUMEDOWN": "gpio-keys",299 "HOME": "mxt224_key_0"300 }301 if iAmRoot:302 touch_device = openTouchDevice(_opt_touch, "file:/dev/input/event0")303elif 'eGalax Inc. eGalaxTouch EXC7200-7368v1.010 ' in devices:304 debug("detected eGalax Inc. eGalaxTouch EXC7200-7368v1.010")305 if iAmRoot:306 touch_device = openTouchDevice(307 _opt_touch,308 "name:eGalax Inc. eGalaxTouch EXC7200-7368v1.010 ")309 mouse_device = openMouseDevice(_opt_mouse, None)310 keyboard_device = openKeyboardDevice(_opt_keyboard)311elif iAmRoot:312 debug("hardware detection uses generic defaults")313 # Unknown platform, guessing best possible defaults for devices314 _d = devices.split("\n\n")315 try:316 power_devname = re.findall('Name=\"([^"]*)\"', [i for i in _d if "power" in i.lower()][0])[0]317 except IndexError:318 power_devname = "gpio-keys"319 touch_device = None320 try:321 touch_device_f = "file:/dev/input/" + re.findall('[ =](event[0-9]+)\s', [i for i in _d if "touch" in i.lower()][0])[0]322 except IndexError:323 touch_device_f = None324 touch_device = openTouchDevice(_opt_touch, touch_device_f)325 mouse_device = None326 try:327 mouse_device_f = "file:/dev/input/" + re.findall('[ =](event[0-9]+)\s', [i for i in _d if "Mouse" in i][0])[0]328 except IndexError:329 mouse_device_f = None330 mouse_device = openMouseDevice(_opt_mouse, mouse_device_f)331 keyboard_device = openKeyboardDevice(_opt_keyboard)332 hwKeyDevice = {333 "POWER": power_devname,334 "VOLUMEUP": "gpio-keys",335 "VOLUMEDOWN": "gpio-keys",336 "HOME": "gpio-keys"337 }338 if isinstance(mouse_device, fmbtuinput.Mouse):339 time.sleep(1)340 mouse_device.move(-4096, -4096)341 mouse_device.setXY(0, 0)342 del _d343if iAmRoot and g_debug:344 debug("touch device: %s" % (touch_device,))345 debug("mouse device: %s" % (mouse_device,))346 debug("keyb device: %s" % (keyboard_device,))347if iAmRoot and _opt_keyboard and "keyboard_device" not in globals():348 # Use forced keyboard with any hardware type349 keyboard_device = openKeyboardDevice(_opt_keyboard)350if "touch_device" in globals() and touch_device:351 mtInputDevFd = touch_device._fd352if "keyboard_device" in globals() and keyboard_device:353 kbInputDevFd = keyboard_device._fd354# Read input devices355deviceToEventFile = {}356for _l in devices.splitlines():357 if _l.startswith('N: Name="'): _device = _l.split('"')[1]358 elif _l.startswith("H: Handlers=") and "event" in _l:359 try: deviceToEventFile[_device] = "/dev/input/" + re.findall("(event[0-9]+)", _l)[0]360 except Exception, e: pass361screenWidth = None362screenHeight = None363# Connect to X server, get root window size for screenshots364display = None365if g_Xavailable:366 def resetXConnection():367 global display, current_screen, root_window, X_AllPlanes368 if display != None:369 libX11.XCloseDisplay(display)370 display = libX11.XOpenDisplay(X_NULL)371 if display == 0 or display == None:372 error("cannot connect to X server")373 current_screen = libX11.XDefaultScreen(display)374 root_window = libX11.XRootWindow(display, current_screen)375 X_AllPlanes = libX11.XAllPlanes()376 resetXConnection()377 ref = ctypes.byref378 __rw = ctypes.c_uint(0)379 __x = ctypes.c_int(0)380 __y = ctypes.c_int(0)381 root_width = ctypes.c_uint(0)382 root_height = ctypes.c_uint(0)383 __bwidth = ctypes.c_uint(0)384 root_depth = ctypes.c_uint(0)385 libX11.XGetGeometry(display, root_window, ref(__rw), ref(__x), ref(__y),386 ref(root_width), ref(root_height), ref(__bwidth),387 ref(root_depth))388 cMinKeycode = ctypes.c_int(0)389 cMaxKeycode = ctypes.c_int(0)390 cKeysymsPerKeycode = ctypes.c_int(0)391 libX11.XDisplayKeycodes(display, ref(cMinKeycode), ref(cMaxKeycode))392 keysyms = libX11.XGetKeyboardMapping(display,393 cMinKeycode,394 (cMaxKeycode.value - cMinKeycode.value) + 1,395 ref(cKeysymsPerKeycode))396 shiftModifier = libX11.XKeysymToKeycode(display, libX11.XStringToKeysym("Shift_R"))397 screenWidth = root_width.value398 screenHeight = root_height.value399def read_cmd():400 return sys.stdin.readline().strip()401def _encode(obj):402 return base64.b64encode(cPickle.dumps(obj))403def _decode(string):404 return cPickle.loads(base64.b64decode(string))405def write_response(ok, value):406 if ok: p = "FMBTAGENT OK "407 else: p = "FMBTAGENT ERROR "408 if not g_debug:409 response = "%s%s\n" % (p, _encode(value))410 else:411 response = "%s%s\n" % (p, value)412 sys.stdout.write(response)413 sys.stdout.flush()414def sendHwTap(x, y, button):415 try:416 if touch_device:417 touch_device.tap(x, y)418 else:419 mouse_device.tap(x, y, button)420 return True, None421 except Exception, e:422 return False, str(e)423def sendHwMove(x, y):424 try:425 if touch_device:426 touch_device.move(x, y)427 else:428 mouse_device.move(x, y)429 return True, None430 except Exception, e:431 return False, str(e)432def sendRelMove(x, y):433 try:434 mouse_device.setXY(0,0)435 mouse_device.move(x, y)436 mouse_device.setXY(0,0)437 return True, None438 except Exception, e:439 return False, str(e)440def sendHwFingerDown(x, y, button):441 try:442 if touch_device:443 touch_device.pressFinger(button, x, y)444 else:445 mouse_device.move(x, y)446 mouse_device.press(button)447 return True, None448 except Exception, e:449 return False, str(e)450def sendHwFingerUp(x, y, button):451 try:452 if touch_device:453 touch_device.releaseFinger(button)454 else:455 mouse_device.move(x, y)456 mouse_device.release(button)457 return True, None458 except Exception, e:459 return False, str(e)460def sendHwKey(keyName, delayBeforePress, delayBeforeRelease):461 keyName = keyName.upper()462 if keyName.startswith("KEY_"):463 keyName = keyName.lstrip("KEY_")464 fd = None465 closeFd = False466 try:467 # Explicit IO device defined for the key?468 inputDevice = deviceToEventFile[hwKeyDevice[keyName]]469 except:470 # Fall back to giving input with keyboard - given that there is one471 if not kbInputDevFd:472 return False, 'No input device for key "%s"' % (keyName,)473 fd = kbInputDevFd474 try: keyCode = _inputKeyNameToCode[keyName]475 except KeyError:476 try: keyCode = fmbtuinput.toKeyCode(keyName)477 except ValueError: return False, 'No keycode for key "%s"' % (keyName,)478 try:479 if not fd:480 fd = os.open(inputDevice, os.O_WRONLY | os.O_NONBLOCK)481 closeFd = True482 except: return False, 'Unable to open input device "%s" for writing' % (inputDevice,)483 if delayBeforePress > 0: time.sleep(delayBeforePress)484 if delayBeforePress >= 0:485 if os.write(fd, struct.pack(_input_event, int(time.time()), 0, _EV_KEY, keyCode, 1)) > 0:486 os.write(fd, struct.pack(_input_event, 0, 0, 0, 0, 0))487 if delayBeforeRelease > 0: time.sleep(delayBeforeRelease)488 if delayBeforeRelease >= 0:489 if os.write(fd, struct.pack(_input_event, int(time.time()), 0, _EV_KEY, keyCode, 0)) > 0:490 os.write(fd, struct.pack(_input_event, 0, 0, 0, 0, 0))491 if closeFd:492 os.close(fd)493 return True, None494def specialCharToXString(c):495 c2s = {'\n': "Return",496 ' ': "space", '!': "exclam", '"': "quotedbl",497 '#': "numbersign", '$': "dollar", '%': "percent",498 '&': "ampersand", "'": "apostrophe",499 '(': "parenleft", ')': "parenright", '*': "asterisk",500 '+': "plus", '-': "minus", '.': "period", '/': "slash",501 ':': "colon", ';': "semicolon", '<': "less", '=': "equal",502 '>': "greater", '?': "question", '@': "at",503 '_': "underscore"}504 return c2s.get(c, c)505def specialCharToUsKeys(c):506 # character -> ([modifier, [modifier...]] keycode)507 c2s = {'\n': ("KEY_ENTER",),508 ' ': ("KEY_SPACE",),509 '`': ("KEY_GRAVE",), '~': ("KEY_LEFTSHIFT", "KEY_GRAVE"),510 '!': ("KEY_LEFTSHIFT", "KEY_1"),511 '@': ("KEY_LEFTSHIFT", "KEY_2"),512 '#': ("KEY_LEFTSHIFT", "KEY_3"),513 '$': ("KEY_LEFTSHIFT", "KEY_4"),514 '%': ("KEY_LEFTSHIFT", "KEY_5"),515 '^': ("KEY_LEFTSHIFT", "KEY_6"),516 '&': ("KEY_LEFTSHIFT", "KEY_7"),517 '*': ("KEY_LEFTSHIFT", "KEY_8"),518 '(': ("KEY_LEFTSHIFT", "KEY_9"),519 ')': ("KEY_LEFTSHIFT", "KEY_0"),520 '-': ("KEY_MINUS",), '_': ("KEY_LEFTSHIFT", "KEY_MINUS"),521 '=': ("KEY_EQUAL",), '+': ("KEY_LEFTSHIFT", "KEY_EQUAL"),522 '\t': ("KEY_TAB",),523 '[': ("KEY_LEFTBRACE",), '{': ("KEY_LEFTSHIFT", "KEY_LEFTBRACE"),524 ']': ("KEY_RIGHTBRACE",), '}': ("KEY_LEFTSHIFT", "KEY_RIGHTBRACE"),525 ';': ("KEY_SEMICOLON",), ':': ("KEY_LEFTSHIFT", "KEY_SEMICOLON"),526 "'": ("KEY_APOSTROPHE",), '"': ("KEY_LEFTSHIFT", "KEY_APOSTROPHE"),527 '\\': ("KEY_BACKSLASH",), '|': ("KEY_LEFTSHIFT", "KEY_BACKSLASH"),528 ',': ("KEY_COMMA",), '<': ("KEY_LEFTSHIFT", "KEY_COMMA"),529 '.': ("KEY_DOT",), '>': ("KEY_LEFTSHIFT", "KEY_DOT"),530 '/': ("KEY_SLASH",), '?': ("KEY_LEFTSHIFT", "KEY_SLASH"),531 }532 return c2s.get(c, c)533mtEvents = {} # slot -> (tracking_id, x, y)534def inputEventSend(inputDevFd, eventType, event, param):535 t = time.time()536 tsec = int(t)537 tusec = int(1000000*(t-tsec))538 os.write(inputDevFd, struct.pack(_input_event,539 tsec, tusec, eventType, event, param))540def mtEventSend(eventType, event, param):541 """multitouch device event"""542 return inputEventSend(mtInputDevFd, eventType, event, param)543def mtGestureStart(x, y):544 mtGestureStart.trackingId += 1545 trackingId = mtGestureStart.trackingId546 for freeSlot in xrange(16):547 if not freeSlot in mtEvents: break548 else: raise ValueError("No free multitouch event slots available")549 mtEvents[freeSlot] = [trackingId, x, y]550 mtEventSend(_EV_ABS, _ABS_MT_SLOT, freeSlot)551 mtEventSend(_EV_ABS, _ABS_MT_TRACKING_ID, trackingId)552 mtEventSend(_EV_ABS, _ABS_MT_POSITION_X, x)553 mtEventSend(_EV_ABS, _ABS_MT_POSITION_Y, y)554 mtEventSend(_EV_ABS, _ABS_X, x)555 mtEventSend(_EV_ABS, _ABS_Y, y)556 mtEventSend(0, 0, 0) # SYNC557 return freeSlot558mtGestureStart.trackingId = 0559def mtGestureMove(slot, x, y):560 if x == mtEvents[slot][1] and y == mtEvents[slot][2]: return561 mtEventSend(_EV_ABS, _ABS_MT_SLOT, slot)562 mtEventSend(_EV_ABS, _ABS_MT_TRACKING_ID, mtEvents[slot][0])563 if x != mtEvents[slot][1] and 0 <= x <= root_width:564 mtEventSend(_EV_ABS, _ABS_MT_POSITION_X, x)565 mtEvents[slot][1] = x566 if y != mtEvents[slot][2] and 0 <= y <= root_height:567 mtEventSend(_EV_ABS, _ABS_MT_POSITION_Y, y)568 mtEvents[slot][2] = y569 if 0 <= x <= root_width:570 mtEventSend(_EV_ABS, _ABS_X, x)571 if 0 <= y <= root_height:572 mtEventSend(_EV_ABS, _ABS_Y, y)573 mtEventSend(0, 0, 0)574def mtGestureEnd(slot):575 mtEventSend(_EV_ABS, _ABS_MT_SLOT, slot)576 mtEventSend(_EV_ABS, _ABS_MT_TRACKING_ID, -1)577 mtEventSend(0, 0, 0) # SYNC578 del mtEvents[slot]579def mtLinearGesture(listOfStartEndPoints, duration, movePoints, sleepBeforeMove=0, sleepAfterMove=0):580 # listOfStartEndPoints: [ [(finger1startX, finger1startY), (finger1endX, finger1endY)],581 # [(finger2startX, finger2startY), (finger2endX, finger2endY)], ...]582 startPoints = [startEnd[0] for startEnd in listOfStartEndPoints]583 xDist = [startEnd[1][0] - startEnd[0][0] for startEnd in listOfStartEndPoints]584 yDist = [startEnd[1][1] - startEnd[0][1] for startEnd in listOfStartEndPoints]585 movePointsF = float(movePoints)586 fingers = []587 for (x, y) in startPoints:588 fingers.append(mtGestureStart(x, y))589 if sleepBeforeMove > 0: time.sleep(sleepBeforeMove)590 if movePoints > 0:591 intermediateSleep = float(duration) / movePoints592 for i in xrange(1, movePoints + 1):593 if intermediateSleep > 0:594 time.sleep(intermediateSleep)595 for fingerIndex, finger in enumerate(fingers):596 mtGestureMove(finger,597 startPoints[fingerIndex][0] + int(xDist[fingerIndex]*i/movePointsF),598 startPoints[fingerIndex][1] + int(yDist[fingerIndex]*i/movePointsF))599 if sleepAfterMove > 0: time.sleep(sleepAfterMove)600 for finger in fingers:601 mtGestureEnd(finger)602 return True, None603def typeCharX(origChar):604 modifiers = []605 c = specialCharToXString(origChar)606 keysym = libX11.XStringToKeysym(c)607 if keysym == NoSymbol:608 return False609 keycode = libX11.XKeysymToKeycode(display, keysym)610 first = (keycode - cMinKeycode.value) * cKeysymsPerKeycode.value611 try:612 if chr(keysyms[first + 1]) == origChar:613 modifiers.append(shiftModifier)614 except ValueError: pass615 for m in modifiers:616 libXtst.XTestFakeKeyEvent(display, m, X_True, X_CurrentTime)617 libXtst.XTestFakeKeyEvent(display, keycode, X_True, X_CurrentTime)618 libXtst.XTestFakeKeyEvent(display, keycode, X_False, X_CurrentTime)619 for m in modifiers[::-1]:620 libXtst.XTestFakeKeyEvent(display, m, X_False, X_CurrentTime)621 return True622def typeCharHw(origChar):623 for c in origChar:624 modifiers = []625 keyCode = None626 c = specialCharToUsKeys(c)627 if isinstance(c, tuple):628 modifiers = c[:-1]629 keyCode = c[-1]630 elif c in string.uppercase:631 modifiers = ["KEY_LEFTSHIFT"]632 keyCode = "KEY_" + c633 elif c in string.lowercase or c in string.digits:634 keyCode = "KEY_" + c.upper()635 else:636 # do not know how to type the character637 pass638 if keyCode:639 for m in modifiers:640 keyboard_device.press(m)641 keyboard_device.tap(keyCode)642 for m in modifiers[::-1]:643 keyboard_device.release(m)644 return True645if g_Xavailable:646 typeChar = typeCharX647else:648 typeChar = typeCharHw649def typeSequence(s, delayBetweenChars=0):650 skipped = []651 for c in s:652 if not typeChar(c):653 skipped.append(c)654 if delayBetweenChars != 0:655 time.sleep(delayBetweenChars)656 if skipped: return False, skipped657 else: return True, skipped658def takeScreenshotOnX():659 image_p = libX11.XGetImage(display, root_window,660 0, 0, root_width, root_height,661 X_AllPlanes, X_ZPixmap)662 image = image_p[0]663 # FMBTRAWX11 image format header:664 # FMBTRAWX11 [width] [height] [color depth] [bits per pixel]<linefeed>665 # Binary data666 rawfmbt_header = "FMBTRAWX11 %d %d %d %d\n" % (667 image.width, image.height, root_depth.value, image.bits_per_pixel)668 rawfmbt_data = ctypes.string_at(image.data, image.height * image.bytes_per_line)669 compressed_image = rawfmbt_header + zlib.compress(rawfmbt_data, 3)670 libX11.XDestroyImage(image_p)671 return True, compressed_image672def westonTakeScreenshotRoot(retry=2):673 if westonTakeScreenshotRoot.ssFilenames == None:674 westonTakeScreenshotRoot.ssFilenames = findWestonScreenshotFilenames()675 if not westonTakeScreenshotRoot.ssFilenames:676 return False, "cannot find weston screenshot directory"677 try:678 for ssFilename in westonTakeScreenshotRoot.ssFilenames:679 if os.access(ssFilename, os.R_OK):680 os.remove(ssFilename)681 keyboard_device.press("KEY_LEFTMETA")682 keyboard_device.tap("s")683 keyboard_device.release("KEY_LEFTMETA")684 time.sleep(0.5)685 # find which screenshot file got created?686 for ssFilename in westonTakeScreenshotRoot.ssFilenames:687 if os.access(ssFilename, os.R_OK):688 break689 else:690 if retry > 0:691 return westonTakeScreenshotRoot(retry-1)692 else:693 return False, "weston did not create any of files %s" % (694 westonTakeScreenshotRoot.ssFilenames,)695 # wait for the screenshot writer to finish696 writerPid = fuser(ssFilename)697 if writerPid != None:698 time.sleep(0.1)699 while fuser(ssFilename, [writerPid]) != None:700 time.sleep(0.1)701 shutil.move(ssFilename, "/tmp/screenshot.png")702 os.chmod("/tmp/screenshot.png", 0666)703 except Exception, e:704 return False, str(e)705 return True, None706westonTakeScreenshotRoot.ssFilenames = None707def takeScreenshotOnWeston():708 if iAmRoot:709 rv, status = westonTakeScreenshotRoot()710 else:711 rv, status = subAgentCommand("root", "tizen", "ss weston-root")712 if rv == False:713 return rv, status714 return True, file("/tmp/screenshot.png").read()715def fuser(filename, usualSuspects=None):716 """Returns the pid of a user of given file, or None"""717 filepath = os.path.realpath(filename)718 if not os.access(filepath, os.R_OK):719 raise ValueError('No such file: "%s"' % (filename,))720 if usualSuspects == None:721 procFds = glob.glob("/proc/[1-9][0-9][0-9]*/fd/*")722 else:723 procFds = []724 for pid in usualSuspects:725 procFds.extend(glob.glob("/proc/%s/fd/*" % (pid,)))726 for symlink in procFds:727 try:728 if os.path.realpath(symlink) == filepath:729 return int(symlink.split('/')[2])730 except OSError:731 pass732def findWestonScreenshotFilenames():733 # find weston cwd734 dirs = []735 for exe in glob.glob("/proc/[1-9][0-9][0-9]*/exe"):736 try:737 if os.path.realpath(exe) == "/usr/bin/weston":738 dirs.append(os.path.realpath(os.path.dirname(exe) + "/cwd"))739 except OSError:740 pass741 return [d + "/wayland-screenshot.png" for d in sorted(set(dirs))]742if g_Xavailable:743 takeScreenshot = takeScreenshotOnX744else:745 takeScreenshot = takeScreenshotOnWeston746def shellSOE(command, asyncStatus, asyncOut, asyncError, usePty):747 if usePty:748 command = '''python -c "import pty; pty.spawn(%s)" ''' % (repr(shlex.split(command)),),749 if (asyncStatus, asyncOut, asyncError) != (None, None, None):750 # prepare for decoupled asynchronous execution751 if asyncStatus == None: asyncStatus = "/dev/null"752 if asyncOut == None: asyncOut = "/dev/null"753 if asyncError == None: asyncError = "/dev/null"754 try:755 stdinFile = file("/dev/null", "r")756 stdoutFile = file(asyncOut, "a+")757 stderrFile = file(asyncError, "a+", 0)758 statusFile = file(asyncStatus, "a+")759 except IOError, e:760 return False, (None, None, e)761 try:762 if os.fork() > 0:763 # parent returns after successful fork, there no764 # direct visibility to async child process beyond this765 # point.766 stdinFile.close()767 stdoutFile.close()768 stderrFile.close()769 statusFile.close()770 return True, (0, None, None) # async parent finishes here771 except OSError, e:772 return False, (None, None, e)773 os.setsid()774 else:775 stdinFile = subprocess.PIPE776 stdoutFile = subprocess.PIPE777 stderrFile = subprocess.PIPE778 try:779 p = subprocess.Popen(command, shell=True,780 stdin=stdinFile,781 stdout=stdoutFile,782 stderr=stderrFile,783 close_fds=True)784 except Exception, e:785 return False, (None, None, e)786 if asyncStatus == None and asyncOut == None and asyncError == None:787 # synchronous execution, read stdout and stderr788 out, err = p.communicate()789 else:790 # asynchronous execution, store status to file791 statusFile.write(str(p.wait()) + "\n")792 statusFile.close()793 out, err = None, None794 sys.exit(0) # async child finishes here795 return True, (p.returncode, out, err)796def waitOutput(nonblockingFd, acceptedOutputs, timeout, pollInterval=0.1):797 start = time.time()798 endTime = start + timeout799 s = ""800 try: s += nonblockingFd.read()801 except IOError: pass802 foundOutputs = [ao for ao in acceptedOutputs if ao in s]803 while len(foundOutputs) == 0 and time.time() < endTime:804 time.sleep(pollInterval)805 try: s += nonblockingFd.read()806 except IOError: pass807 foundOutputs = [ao for ao in acceptedOutputs if ao in s]808 return foundOutputs, s809_subAgents = {}810def openSubAgent(username, password):811 p = subprocess.Popen('''python -c 'import pty; pty.spawn(["su", "-c", "python /tmp/fmbttizen-agent.py --sub-agent", "-", "%s"])' ''' % (username,),812 shell=True,813 stdin=subprocess.PIPE,814 stdout=subprocess.PIPE,815 stderr=subprocess.PIPE)816 # Read in non-blocking mode to ensure agent starts correctly817 fl = fcntl.fcntl(p.stdout.fileno(), fcntl.F_GETFL)818 fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, fl | os.O_NONBLOCK)819 output2 = ""820 seenPrompts, output1 = waitOutput(p.stdout, ["Password:", "FMBTAGENT"], 5.0)821 if "Password:" in seenPrompts:822 p.stdin.write(password + "\r")823 output1 = ""824 seenPrompts, output2 = waitOutput(p.stdout, ["FMBTAGENT"], 5.0)825 if not "FMBTAGENT" in seenPrompts:826 p.terminate()827 return (None, 'fMBT agent with username "%s" does not answer.' % (username,),828 output1 + output2)829 # Agent is alive, continue in blocking mode830 fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, fl)831 return p, "", ""832def subAgentCommand(username, password, cmd):833 if not username in _subAgents:834 process, output, error = openSubAgent(username, password)835 if process == None:836 return None, (-1, output, error)837 else:838 _subAgents[username] = process839 p = _subAgents[username]840 p.stdin.write(cmd + "\r")841 p.stdin.flush()842 answer = p.stdout.readline().rstrip()843 if answer.startswith("FMBTAGENT OK "):844 return True, _decode(answer[len("FMBTAGENT OK "):])845 else:846 return False, _decode(answer[len("FMBTAGENT ERROR "):])847def closeSubAgents():848 for username in _subAgents:849 subAgentCommand(username, None, "quit")850if __name__ == "__main__":851 try:852 origTermAttrs = termios.tcgetattr(sys.stdin.fileno())853 hasTerminal = True854 except termios.error:855 origTermAttrs = None856 hasTerminal = False857 if hasTerminal and not "--keep-echo" in sys.argv and not "--debug" in sys.argv:858 # Disable terminal echo859 newTermAttrs = origTermAttrs860 newTermAttrs[3] = origTermAttrs[3] & ~termios.ECHO861 termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, newTermAttrs)862 if "--no-x" in sys.argv:863 debug("X disabled")864 g_Xavailable = False865 platformInfo = {}866 platformInfo["input devices"] = fmbtuinput._g_deviceNames.keys()867 # Send version number, enter main loop868 write_response(True, platformInfo)869 cmd = read_cmd()870 while cmd:871 if cmd.startswith("bl "): # set display backlight time872 if iAmRoot:873 timeout = int(cmd[3:].strip())874 try:875 file("/opt/var/kdb/db/setting/lcd_backlight_normal","wb").write(struct.pack("ii",0x29,timeout))876 write_response(True, None)877 except Exception, e: write_response(False, e)878 else:879 write_response(*subAgentCommand("root", "tizen", cmd))880 elif cmd.startswith("er "): # event recorder881 if iAmRoot:882 cmd, arg = cmd.split(" ", 1)883 if arg.startswith("start "):884 filterOpts = _decode(arg.split()[1])885 if touch_device:886 filterOpts["touchScreen"] = touch_device887 fmbtuinput.startQueueingEvents(filterOpts)888 write_response(True, None)889 elif arg == "stop":890 events = fmbtuinput.stopQueueingEvents()891 write_response(True, None)892 elif arg == "fetch":893 events = fmbtuinput.fetchQueuedEvents()894 write_response(True, events)895 else:896 write_response(*subAgentCommand("root", "tizen", cmd))897 elif cmd.startswith("gd"): # get display status898 try:899 p = subprocess.Popen(['/usr/bin/xset', 'q'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)900 out, err = p.communicate()901 if "Monitor is Off" in out: write_response(True, "Off")902 elif "Monitor is On" in out: write_response(True, "On")903 else: write_response(False, err)904 except Exception, e: write_response(False, e)905 elif cmd.startswith("tm "): # touch move(x, y)906 xs, ys = cmd[3:].strip().split()907 if g_Xavailable:908 libXtst.XTestFakeMotionEvent(display, current_screen, int(xs), int(ys), X_CurrentTime)909 libX11.XFlush(display)910 else:911 if iAmRoot: rv, msg = sendHwMove(int(xs), int(ys))912 else: rv, msg = subAgentCommand("root", "tizen", cmd)913 write_response(True, None)914 elif cmd.startswith("tr "): # relative move(x, y)915 xd, yd = cmd[3:].strip().split()916 if iAmRoot: rv, msg = sendRelMove(int(xd), int(yd))917 else: rv, msg = subAgentCommand("root", "tizen", cmd)918 write_response(True, None)919 elif cmd.startswith("tt "): # touch tap(x, y, button)920 x, y, button = [int(i) for i in cmd[3:].strip().split()]921 if g_Xavailable:922 libXtst.XTestFakeMotionEvent(display, current_screen, x, y, X_CurrentTime)923 libXtst.XTestFakeButtonEvent(display, button, X_True, X_CurrentTime)924 libXtst.XTestFakeButtonEvent(display, button, X_False, X_CurrentTime)925 libX11.XFlush(display)926 rv, msg = True, None927 else:928 if iAmRoot: rv, msg = sendHwTap(x, y, button-1)929 else: rv, msg = subAgentCommand("root", "tizen", cmd)930 write_response(rv, msg)931 elif cmd.startswith("td "): # touch down(x, y, button)932 xs, ys, button = cmd[3:].strip().split()933 button = int(button)934 if g_Xavailable:935 libXtst.XTestFakeMotionEvent(display, current_screen, int(xs), int(ys), X_CurrentTime)936 libXtst.XTestFakeButtonEvent(display, button, X_True, X_CurrentTime)937 libX11.XFlush(display)938 else:939 if iAmRoot: rv, msg = sendHwFingerDown(int(xs), int(ys), button-1)940 else: rv, msg = subAgentCommand("root", "tizen", cmd)941 write_response(True, None)942 elif cmd.startswith("tu "): # touch up(x, y, button)943 xs, ys, button = cmd[3:].strip().split()944 button = int(button)945 if g_Xavailable:946 libXtst.XTestFakeMotionEvent(display, current_screen, int(xs), int(ys), X_CurrentTime)947 libXtst.XTestFakeButtonEvent(display, button, X_False, X_CurrentTime)948 libX11.XFlush(display)949 else:950 if iAmRoot: rv, msg = sendHwFingerUp(int(xs), int(ys), button-1)951 else: rv, msg = subAgentCommand("root", "tizen", cmd)952 write_response(True, None)953 elif cmd.startswith("kd "): # hw key down954 if iAmRoot: rv, msg = sendHwKey(cmd[3:], 0, -1)955 else: rv, msg = subAgentCommand("root", "tizen", cmd)956 write_response(rv, msg)957 elif cmd.startswith("kn"): # list input key names958 if "hwKeyDevice" in globals():959 hk = hwKeyDevice.keys()960 else:961 hk = []962 if "keyboard_device" in globals():963 ik = InputKeys964 else:965 ik = []966 write_response(True, sorted(ik + hk))967 elif cmd.startswith("kp "): # hw key press968 if iAmRoot: rv, msg = sendHwKey(cmd[3:], 0, 0)969 else: rv, msg = subAgentCommand("root", "tizen", cmd)970 write_response(rv, msg)971 elif cmd.startswith("ku "): # hw key up972 if iAmRoot: rv, msg = sendHwKey(cmd[3:], -1, 0)973 else: rv, msg = subAgentCommand("root", "tizen", cmd)974 write_response(rv, msg)975 elif cmd.startswith("kt "): # send x events976 if g_Xavailable:977 rv, skippedSymbols = typeSequence(_decode(cmd[3:]))978 libX11.XFlush(display)979 elif iAmRoot:980 rv, skippedSymbols = typeSequence(_decode(cmd[3:]),981 delayBetweenChars=0.05)982 else:983 rv, skippedSymbols = subAgentCommand("root", "tizen", cmd)984 write_response(rv, skippedSymbols)985 elif cmd.startswith("ml "): # send multitouch linear gesture986 if iAmRoot:987 rv, _ = mtLinearGesture(*_decode(cmd[3:]))988 else:989 rv, _ = subAgentCommand("root", "tizen", cmd)990 write_response(rv, _)991 elif cmd.startswith("ss"): # save screenshot992 if "R" in cmd.split() and g_Xavailable:993 resetXConnection()994 if "weston-root" in cmd.split(): # do Weston root part only995 write_response(*westonTakeScreenshotRoot())996 else:997 rv, compressedImage = takeScreenshot()998 write_response(rv, compressedImage)999 elif cmd.startswith("sd "): # set screen dimensions (width and height)1000 _sw, _sh = cmd[3:].split()1001 screenWidth, screenHeight = int(_sw), int(_sh)1002 if iAmRoot:1003 if touch_device:1004 touch_device.setScreenSize((screenWidth, screenHeight))1005 rv, msg = True, None1006 else:1007 rv, msg = True, "no touch device"1008 else:1009 rv, msg = subAgentCommand("root", "tizen", cmd)1010 write_response(rv, msg)1011 elif cmd.startswith("sa "): # set screenshot rotation angle (degrees)1012 if iAmRoot:1013 if touch_device:1014 _sa = int(cmd[3:])1015 # compensate it with opposite rotation1016 touch_device.setScreenAngle(-_sa)1017 rv, msg = True, None1018 else:1019 rv, msg = True, "no touch device"1020 else:1021 rv, msg = subAgentCommand("root", "tizen", cmd)1022 write_response(rv, msg)1023 elif cmd.startswith("es "): # execute shell1024 shellCmd, username, password, asyncStatus, asyncOut, asyncError, usePty = _decode(cmd[3:])1025 if username == "":1026 rv, soe = shellSOE(shellCmd, asyncStatus, asyncOut, asyncError, usePty)1027 else:1028 rv, soe = subAgentCommand(username, password,1029 "es " + _encode((shellCmd, "", "", asyncStatus, asyncOut, asyncError, usePty)))1030 write_response(rv, soe)1031 elif cmd.startswith("quit"): # quit1032 write_response(rv, True)1033 break1034 else:1035 write_response(False, 'Unknown command: "%s"' % (cmd,))1036 cmd = read_cmd()1037 closeSubAgents()1038 if g_Xavailable:1039 libX11.XCloseDisplay(display)1040 if hasTerminal:...
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!!