def save_make_error_node_screen(self, node): try: Saver.save_crawler_log(self.logPath, "Step : save screenshot ") get_screenshot_command = 'adb -s ' + self.id + ' shell /system/bin/screencap -p /sdcard/screenshot.png' activity = node.currentActivity resource_id = node.resource_id resource_id = resource_id[resource_id.find('/') + 1:] location = node.location local_png = self.screenshotPath + '/' + str( self.saveScreenNum) + '-' + str(activity) + '-' + str( resource_id) + '-' + str(location[0]) + '-' + str( location[1]) + '.png' pull_screenshot_command = 'adb -s ' + self.id + ' pull /sdcard/screenshot.png ' + local_png os.system(get_screenshot_command) os.system(pull_screenshot_command) self.saveScreenNum += 1 i = Image.open(local_png) for w in range(3): bounds = node.bounds for x in range(bounds[0] + w, bounds[2] - w): i.putpixel((x, bounds[1] + 1 + w), (255, 0, 0)) i.putpixel((x, bounds[3] - 1 - w), (255, 0, 0)) for y in range(bounds[1] + w, bounds[3] - w): i.putpixel((bounds[0] + 1 + w, y), (255, 0, 0)) i.putpixel((bounds[2] - 1 - w, y), (255, 0, 0)) i.save(local_png) del get_screenshot_command, activity, resource_id, location, pull_screenshot_command, local_png, i del node, bounds gc.collect() except Exception, e: print(str(e)) Saver.save_crawler_log(self.logPath, "save screen error")
def crawl_init_nodes(plan, app, device, page_before_run): Saver.save_crawler_log_both(plan.logPath, device.logPath, "Step : run init nodes") device.update_uncrawled_nodes(page_before_run) if page_before_run.currentActivity != app.mainActivity or page_before_run.package != app.packageName: page_now = pageController.get_page_info(plan, app, device) if page_before_run.clickableNodesNum != 0: device.update_crawl_page(page_before_run.nodesInfoList) if page_before_run.clickableNodesNum > 0: page_now = crawl_clickable_nodes(plan, app, device, page_before_run, page_now, True) if page_before_run.longClickableNodesNum > 0: page_now = crawl_longclickable_nodes(plan, app, device, page_before_run, page_now, True) if page_before_run.editTextsNum > 0: page_now = crawl_edittext(plan, app, device, page_before_run, page_now, False) del plan, app, device, page_before_run return page_now else: Saver.save_crawler_log_both(plan.logPath, device.logPath, 'Is in ' + app.mainActivity) del plan, app, device return page_before_run
def get_page_info(plan, app, device): if Setting.TimeModel == 'Limit': time_now = datetime.datetime.now() if (time_now - device.beginCrawlTime).seconds > (Setting.LimitTime * 60): Saver.save_crawler_log_both( plan.logPath, device.logPath, "Step : crawl time out , finish crawl.") del time_now return None Saver.save_crawler_log(device.logPath, "get all nodes in this page") page = PageInfo.Page() result = False time = 0 while not result: try: if time > 2: appController.click_back(device) get_uidump_xml_file(device) break get_uidump_xml_file(device) dom = xml.dom.minidom.parse(device.logPath + '/Uidump.xml') result = True except Exception, e: time += 1 print(str(e)) result = False
def get_need_crawl_page(plan, app, device, page_before_run, page_after_run): Saver.save_crawler_log(device.logPath, "Step : get need crawl page now ...") if len(page_after_run.nodesList) == 0: page_after_run = get_page_info(plan, app, device) if page_after_run is not None and len(page_after_run.nodesList) != 0: for node in page_after_run.nodesList: if node in page_before_run.nodesList: page_after_run.remove_clickable_node(node) page_after_run.remove_scrollable_node(node) page_after_run.remove_longclickable_node(node) page_after_run.remove_edit_text(node) # after type text in edit text, text & bounds will change , don't need to crawl the edit text again if node.isEditText: info = [ node.index, node.resource_id, node.package, node.content_desc ] for n in page_after_run.editTexts: i = [n.index, n.resource_id, n.package, n.content_desc] if i == info: page_after_run.remove_edit_text(n) break del i, n del node del plan, app, device, page_before_run return page_after_run
def type_text(device, edittext, text): Saver.save_crawler_log(device.logPath, "type : " + text) tap_node(device, edittext) command = 'adb -s ' + device.id + ' shell input text ' + text os.system(command) edittext.update_operation('type') del device, edittext, text, command
def re_crawl_mack_error_node(plan, app, device, page_before_run, node, activity): appController.start_activity(device, app.packageName, activity) page_now = get_page_info(plan, app, device) if nodeController.recover_node_shown(plan, app, device, page_now, page_before_run, node): device.save_make_error_node_screen(node) if node.crawlOperation == 'tap': appController.tap_node(device, node) elif node.crawlOperation == 'longclick': appController.long_click_node(device, node) elif node.crawlOperation == 'type': t = appController.get_random_text(8) appController.type_text(device, node, t) if not appController.app_is_running(device, app): Saver.save_error_logcat(plan, device) HtmlMaker.make_failed_result_html(plan, app) MailSender.send_failed_mail_necessary(plan, app, device, node) del plan, app, device, page_before_run, node, activity, page_now return False else: HtmlMaker.make_failed_result_html(plan, app) MailSender.send_failed_mail_un_necessary(plan, app, device) del plan, app, device, page_before_run, node, activity, page_now return True
def get_device_name(self): # linux: # adb shell cat /system/build.prop | grep "product" # windows # adb -s 84B5T15A10010101 shell cat /system/build.prop | findstr "product" device_name = '' try: command = 'adb -s ' + self.id + ' shell cat /system/build.prop | grep "product" ' result = os.popen(command).readlines() for line in result: key = 'ro.product.model=' if key in line: device_name = line[line.find(key) + len(key):-2] break Saver.save_crawler_log(self.logPath, "device name : " + device_name) except Exception, e: print(e) command = 'adb -s ' + self.id + ' shell cat /system/build.prop | findstr "product" ' result = os.popen(command).readlines() for line in result: key = 'ro.product.model=' if key in line: device_name = line[line.find(key) + len(key):-2] del key break Saver.save_crawler_log(self.logPath, "device name : " + device_name)
def drag_screen_to_left(device): Saver.save_crawler_log(device.logPath, "Step : drag screen to left") # x_max = str(int(device.screenResolution[0]) - 50) # x_min = str(int(resolution[0]) * 0.5)[:str(int(resolution[0]) * 0.5).index('.')] # command = 'adb -s ' + device.id + ' shell input swipe ' + x_max + ' 100 ' + '20' + ' 100' command = 'adb -s ' + device.id + ' shell input keyevent 22' os.system(command) del command, device
def get_login_activity(self, plan): try: login_activity = Setting.AppLoginActivity[self.packageName] del plan return login_activity except Exception as e: Saver.save_crawler_log(plan.logPath, str(e)) del plan, e return ''
def node_is_shown_in_page(device, node, page): if node in page.nodesList: Saver.save_crawler_log(device.logPath, "node is shown in page now") del device, node, page return True else: Saver.save_crawler_log(device.logPath, "node is not shown in page now") del device, node, page return False
def uninstall_app(device, package_name): try: Saver.save_crawler_log(device.logPath, 'Step : uninstall app : ' + package_name) command = 'adb -s ' + device.id + " uninstall " + package_name os.system(command) del device, package_name, command except: del device, package_name Saver.save_crawler_log(device.logPath, 'uninstall app catch exception')
def get_init_cases(self, plan): try: init_cases = Setting.InitCases[self.packageName] del plan return init_cases except Exception as e: Saver.save_crawler_log(plan.logPath, str(e)) del e, plan return []
def remove_uidump_xml_file(device): try: Saver.save_crawler_log(device.logPath, "Step : remove uidunp xml") remove_xml_file = device.logPath + '/Uidump.xml' os.remove(remove_xml_file) del remove_xml_file except Exception, e: print(str(e)) Saver.save_crawler_log(device.logPath, "no uidump xml")
def install_app(device, apk_path): try: if os.path.exists(apk_path): Saver.save_crawler_log(device.logPath, 'Step : install app : ' + apk_path) command = 'adb -s ' + device.id + " install -r " + apk_path os.system(command) del device, apk_path, command except: del device, apk_path Saver.save_crawler_log(device.logPath, 'install app catch exception')
def close_sys_alert(plan, app, device, page_now): if page_now is None: return page_now for node in page_now.clickableNodes: info = [node.package, node.resource_id, node.text] if info in Setting.AuthorizationAlert: Saver.save_crawler_log(device.logPath, "Step : close sys alert") device.save_screen(node, False) tap_node(device, node) page_now = pageController.get_page_info(plan, app, device) return page_now
def get_nodes_list(device): Saver.save_crawler_log(device.logPath, "Step : get nodes list") try: dom = xml.dom.minidom.parse(device.logPath + '/Uidump.xml') root = dom.documentElement nodes = root.getElementsByTagName('node') del dom, root return nodes except Exception, e: print(str(e)) return ''
def app_is_installed(device, package_name): Saver.save_crawler_log(device.logPath, "Step : check app is installed or not") command = 'adb -s ' + device.id + " shell pm list package" result = os.popen(command) lines = result.readlines() for line in lines: if package_name in line and (package_name + '.') not in line: print "app is installed" del command, result, lines, device, line, package_name return True del line Saver.save_crawler_log(device.logPath, "app is not installed") del command, result, lines, device, package_name return False
def init_application(plan, app, device): Saver.save_crawler_log_both(plan.logPath, device.logPath, "Step : init application") if Setting.RunInitNodes: appController.start_activity(device, app.packageName, app.launcherActivity) while True: launcherPage = pageController.get_page_info(plan, app, device) if launcherPage.clickableNodesNum == 0: Saver.save_crawler_log_both(plan.logPath, device.logPath, 'scroll to left') appController.drag_screen_to_left(device) else: Saver.save_crawler_log_both(plan.logPath, device.logPath, 'stop scroll') break Saver.save_crawler_log_both(plan.logPath, device.logPath, 'Step : init nodes run begin') crawl_init_nodes(plan, app, device, launcherPage) del launcherPage if Setting.RunInitCase: run_init_cases(plan, app, device) # when go in mainActivity, will add the nodes in MainActivity to device.unCrawledNodes # if crawl main Nodes , after start mainActivity, these nodes can't be added to the page, will get unCrawlable page device.unCrawledNodes = [] del plan, app, device
def get_view_list(self, plan, id_dict): try: id_list = id_dict[self.packageName] views = [] if len(id_list) != 0: for device_id in id_list: resource_id = self.packageName + ':id/' + device_id views.append(resource_id) del resource_id del id_list, plan return views except Exception as e: Saver.save_crawler_log(plan.logPath, str(e)) del id_dict, e, plan return []
def get_unCrawlViews(self, plan): try: unCrawlViews = [] for key, value in Setting.UnCrawlViews[self.packageName].items(): if value == 'id': resource_id = self.packageName + ':id/' + key unCrawlViews.append(resource_id) del resource_id if value == 'text': unCrawlViews.append(key) del key, value return unCrawlViews except Exception as e: Saver.save_crawler_log(plan.logPath, str(e)) del plan, e return []
def get_screen_resolution(self): Saver.save_crawler_log(self.logPath, "Step : get screen resolution") command = 'adb -s ' + self.id + ' shell wm size' resolution = [] result = os.popen(command).readlines() x = '' y = '' for line in result: if 'Physical size: ' in line: r = re.findall(r'\d+', line) x = r[0] y = r[1] resolution.append(x) resolution.append(y) Saver.save_crawler_log(self.logPath, resolution) return resolution
def get_launcher_activity(self, plan): try: command = 'aapt dump badging ' + self.apkPath result = os.popen(command).readlines() activity_head = "launchable-activity: name='" end = "' " for line in result: if activity_head in line: activity_name = line[line.index(activity_head) + len(activity_head):line.index(end)] del plan, command, result, line, activity_head, end return activity_name del plan, command, result, activity_head, end return '' except Exception as e: Saver.save_crawler_log(plan.logPath, str(e)) del plan, e return ''
def save_screen_jump_out(self, package, activity): if Setting.SaveJumpOutScreen: try: Saver.save_crawler_log(self.logPath, "Step : jump out . save screenshot ") get_screenshot_command = 'adb -s ' + self.id + ' shell /system/bin/screencap -p /sdcard/screenshot.png' local_png = self.screenshotPath + '/' + str(self.saveScreenNum) + '-' + str(package) + '-' + str( activity) + '-Jump' + str(self.jump_out_time) + '.png' pull_screenshot_command = 'adb -s ' + self.id + ' pull /sdcard/screenshot.png ' + local_png os.system(get_screenshot_command) os.system(pull_screenshot_command) self.saveScreenNum += 1 self.jump_out_time += 1 del get_screenshot_command, local_png, pull_screenshot_command gc.collect() except Exception, e: print (str(e)) Saver.save_crawler_log(self, "save screen error")
def get_app_name(self, plan): try: command = 'aapt dump badging ' + self.apkPath result = os.popen(command).readlines() for line in result: name_head = "application-label-zh-CN:'" if name_head in line: name = line[line.index(name_head) + len(name_head):len(line) - 2] del plan, name_head return name del line del plan, command, result return '' except Exception as e: Saver.save_crawler_log(plan.logPath, str(e)) del plan, e return ""
def crawl_longclickable_nodes(plan, app, device, page_before_run, page_now, init): for node in nodeController.get_random_nodes( page_before_run.longClickableNodes): # if crash and not keep run , break from deep run .page_need_crawled will be None if page_now is None: Saver.save_crawler_log(device.logPath, 'Jump out to crawl') del node break # sometimes the need tap node is not shown after one deep run if not nodeController.recover_node_shown(plan, app, device, page_now, page_before_run, node): continue device.save_screen(node, True) appController.long_click_node(device, node) device.update_crawled_activity(node.currentActivity) device.update_crawled_nodes(node.nodeInfo) device.delete_uncrawled_nodes(node.nodeInfo) # if jump out the test app, try to go back & return the final page page_after_operation = pageController.check_page_after_operation( plan, app, device, page_before_run, node) if page_after_operation is None: Saver.save_crawler_log(device.logPath, 'Jump out to crawl') page_now = page_after_operation break # compare two pages before & after click . # update the after page . leave the new clickable/scrollable/longclickable/edittext nodes only. page_now = pageController.get_need_crawl_page(plan, app, device, page_before_run, page_after_operation) if pageController.page_is_crawlable(app, device, page_now): page_now.add_last_page(page_before_run) page_now.add_entry(node) # deep run if init: page_now = crawl_init_nodes(plan, app, device, page_now) else: page_now = crawl_main_nodes(plan, app, device, page_now) # if page no crawlable nodes , back to last Page, until has crawlable nodes, if back time >3, break page_now = pageController.recover_page_to_crawlable( plan, app, device, page_now) del node del plan, app, device, page_before_run, init return page_now
def start_activity(device, packagename, activity): Saver.save_crawler_log(device.logPath, 'Step : start up activity : ' + activity) time1 = datetime.datetime.now() result = False while not result: command = 'adb -s ' + device.id + ' shell am start -n ' + packagename + '/' + activity os.system(command) if (datetime.datetime.now() - time1).seconds < 10: top_activity_info = pageController.get_top_activity_info(device) top_packagename = top_activity_info['packagename'] top_activity = top_activity_info['activity'] if top_packagename == packagename and top_activity == activity: result = True del top_activity_info, top_packagename, top_activity else: result = True del command del device, packagename, activity, time1, result
def get_package_name(plan, apk_path): try: command = 'aapt dump badging ' + apk_path result = os.popen(command).readlines() end = "' " package_head = "package: name='" for line in result: if package_head in line: package_name = line[line.index(package_head) + len(package_head):line.index(end)] del command, result, package_head, end, apk_path, line return package_name del line del command, result, apk_path, end, package_head return '' except Exception as e: Saver.save_crawler_log(plan.logPath, str(e)) del apk_path, e return ""
def get_screen_resolution(self): Saver.save_crawler_log(self.logPath, "Step : get screen resolution") command = 'adb -s ' + self.id + ' shell dumpsys window' resolution = [] result = os.popen(command).readlines() x = '' y = '' for line in result: if 'init=' in line: r = re.findall(r'\d+', line) x = r[0] y = r[1] del r resolution.append(x) resolution.append(y) Saver.save_crawler_log(self.logPath, resolution) del command, result, x, y return resolution
def get_top_activity_info(device): Saver.save_crawler_log(device.logPath, "Step : get top activity info") # linux: # adb shell dumpsys activity | grep "mFocusedActivity" # windows: # adb shell dumpsys activity | findstr "mFocusedActivity" info = {} # command = 'adb -s ' + device.id + ' shell dumpsys activity | grep "mFocusedActivity"' # sometime mResumedActivity is Right try: command = 'adb -s ' + device.id + ' shell dumpsys activity | grep "mResumedActivity"' result = os.popen(command).read() packagename = '' activity = '' if 'u0' not in result and ' com.' not in result: result = os.popen(command).read() if 'u0 ' in result: packagename = result[result.find('u0 ') + len('u0 '):result.find('/')] elif ' com.' in result: packagename = result[result.find(' com.') + 1:result.find('/')] if ' t' in result: activity = result[result.find('/') + len('/'):result.find(' t')] elif '}' in result: activity = result[result.find('/') + len('/'):result.find('}')] except Exception, e: print(str(e)) command = 'adb -s ' + device.id + ' shell dumpsys activity | findstr "mResumedActivity"' result = os.popen(command).read() packagename = '' activity = '' if 'u0' not in result and ' com.' not in result: result = os.popen(command).read() if 'u0 ' in result: packagename = result[result.find('u0 ') + len('u0 '):result.find('/')] elif ' com.' in result: packagename = result[result.find(' com.') + 1:result.find('/')] if ' t' in result: activity = result[result.find('/') + len('/'):result.find(' t')] elif '}' in result: activity = result[result.find('/') + len('/'):result.find('}')]
def get_need_crawl_page(plan, app, device, page_before_run, page_after_run): Saver.save_crawler_log(device.logPath, "Step : get need crawl page now ...") if page_after_run.nodesNum == 0: page_after_run = get_page_info(plan, app, device) new_nodes_num = 0 if page_after_run is not None and page_after_run.nodesNum != 0: for node in page_after_run.nodesList: if node.nodeInfo in page_before_run.nodesInfoList: page_after_run.remove_clickable_node(node) page_after_run.remove_scrollable_node(node) page_after_run.remove_longclickable_node(node) page_after_run.remove_edit_text(node) # after type text in edit text, text & bounds will change , don't need to crawl the edit text again elif node.isEditText: info = [ node.index, node.resource_id, node.package, node.content_desc ] for n in page_before_run.editTexts: i = [n.index, n.resource_id, n.package, n.content_desc] if i == info: page_after_run.remove_edit_text(node) break del i, n # if all new shown crawable nodes are both crawled, click back to recover page shown elif not device.is_in_hascrawled_nodes( node.nodeInfo) and not device.is_in_uncrawled_nodes( node.nodeInfo): new_nodes_num += 1 del node if page_after_run.clickableNodesNum == page_after_run.longClickableNodesNum == page_after_run.editTextsNum == page_after_run.scrollableNodesNum == 0 \ and new_nodes_num > 0: Saver.save_crawler_log( device.logPath, "Step : no new unCrawled nodes , but has some unCrawlable nodes show , back ..." ) appController.click_back(device) page_after_run = get_page_info(plan, app, device) return get_need_crawl_page(plan, app, device, page_before_run, page_after_run) del plan, app, device, page_before_run return page_after_run