UAT_focusCommand.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. # -*- coding:utf-8 -*-
  2. import time,sys,os
  3. from UAT_tree import UATTree
  4. from UAT_log import error,info,debug
  5. from UAT_PathManage import UATPathManage
  6. from UIParamUtil import UIParamUtil
  7. # from UAT_runnerCommand import UATRunnerCommand
  8. from ssat_sdk.python_uiautomator import PyUIAutomator,DirectionManageAndroid,FocusManageAndroid
  9. import math
  10. import traceback
  11. ERROR = True
  12. INFO = True
  13. DEBUG = True # 上传SVN版本此参数关闭
  14. '''
  15. 采用uiautomator技术,处理界面定位问题,用于移动焦点到目标组件上
  16. '''
  17. class FocusCommand():
  18. cls = "FocusCommand"
  19. UIObjParam = UIParamUtil.UIObjParam
  20. UATParamMap = UIParamUtil.UATParamMap
  21. def __init__(self, runnerCommand):
  22. self.runnerCommand = runnerCommand
  23. self.pyU = PyUIAutomator()
  24. self.dm = DirectionManageAndroid()
  25. self.fm = FocusManageAndroid(self.pyU, self.dm)
  26. self.inLayout= False
  27. '''
  28. 解析option的焦点组件参数,返回focusView或者focus-select组件参数
  29. :param option: option字典
  30. :return 返回 focus焦点参数字典,采用setObjParam可以转换成UIObject识别需要的参数。
  31. 如果为None,则表示不需要焦点选中。
  32. '''
  33. def getFPFromOption(self, option):
  34. focusParam = None
  35. fsParam = option[UATTree.TAB_FOCUS_SELECT]
  36. fvParam = option[UATTree.TAB_FOCUSE_VIEW]
  37. if fsParam[UATTree.FS_Type].__len__() > 1:
  38. if fsParam[UATTree.FS_Type].lower() == "focus":
  39. fsParam["focus"] = True
  40. focusParam = fsParam
  41. elif fsParam[UATTree.FS_Type].lower() == "select":
  42. fsParam["select"] = True
  43. focusParam = fsParam
  44. elif fsParam[UATTree.FS_Type].lower() == "no":
  45. focusParam = None
  46. else:
  47. error(self.cls, "getFPFromOption", "Option %s focus-select参数异常。" % option[UATTree.TAB_NAME], ERROR)
  48. else:
  49. focusParam = fvParam
  50. return focusParam
  51. '''
  52. 解析option的焦点组件参数,返回focusView或者focus-select组件参数.
  53. 在getFPFromOption返回值上,采用setObjParam转换成UIObject识别需要的参数。
  54. :param option: option字典
  55. :return 返回 focus焦点UIObject参数字典.
  56. '''
  57. def getFPObjParam(self, option):
  58. focusParam = self.getFPFromOption(option)
  59. fpObjParam = UIParamUtil.setObjParam(focusParam)
  60. return fpObjParam
  61. '''
  62. 解析存储在UATree里的moveKey字典,得到按键类型、键值数组、最大尝试次数
  63. :param moveKey, parent字典中moveKey字典
  64. :param optionCount: moveKey对应的parent的option个数
  65. :return keyType, keyCodeList, Max_Trye
  66. '''
  67. def parseMoveKey(self,moveKey, optionCount):
  68. if moveKey[UATTree.Max_Try] != "":
  69. Max_Try = int(moveKey[UATTree.Max_Try])
  70. else:
  71. Max_Try = optionCount
  72. findDirection = ["down","up"]
  73. keyType = UATTree.Key_Event
  74. if moveKey[UATTree.Key_Event].__len__() > 1:
  75. findDirection = moveKey[UATTree.Key_Event]
  76. keyType = UATTree.Key_Event
  77. elif moveKey[UATTree.Key_IR].__len__() > 1:
  78. findDirection = moveKey[UATTree.Key_IR]
  79. keyType = UATTree.Key_IR
  80. elif moveKey[UATTree.Key_Input].__len__() > 1:
  81. inputCmd = moveKey[UATTree.Key_Input]
  82. #TODO input情况的处理
  83. return None,None,None
  84. else:
  85. return None,None,None
  86. return keyType, findDirection, Max_Try
  87. '''
  88. 在parent界面,将焦点移动到目标option上。
  89. 焦点定位:根据layout是不是限制焦点范围,进行焦点组件寻找,焦点组件类型:focus、select、focusView、long-click
  90. 目标定位:纯粹是根据optionView配置组建坐标定位
  91. :param parent:当前电视界面的parent字典
  92. :param option:目标option字典
  93. :return True/False
  94. '''
  95. def focusOptionView(self, parent, option,chooseType):
  96. #是否采用layout限制焦点判断范围
  97. layout = parent[UATTree.TAB_LAYOUT]
  98. print "focusOptionView,layout:",layout
  99. self.inLayout = layout[UATTree.Layout_Limit]
  100. # 找到目标optionView参数
  101. layoutUIObj = {}
  102. optionUIObjParam = UIParamUtil.setObjParam(option[UATTree.TAB_OPTION_VIEW])
  103. if self.inLayout == 1:
  104. layoutUIObjParam = UIParamUtil.setObjParam(layout)
  105. else:
  106. layoutUIObjParam = {}
  107. # 获取move key按键
  108. moveKey = parent[UATTree.TAB_MOVE_KEY]
  109. keyType, findDirection,Max_Try = self.parseMoveKey(moveKey, parent[UATTree.TAB_OPTION].__len__())
  110. if keyType is None:
  111. error(self.cls, "focusTargetOption", option[UATTree.TAB_NAME] + " option 读取 move_key失败", ERROR)
  112. return False
  113. #获取optionview的View_sambounds参数
  114. osamBounds = option[UATTree.TAB_OPTION_VIEW][UATTree.View_sambounds]
  115. #获取焦点view参数
  116. focusParam = self.getFPFromOption(option)
  117. focusUIParam = UIParamUtil.setObjParam(focusParam)
  118. if focusParam is None:
  119. fsamBounds = []
  120. else:
  121. fsamBounds = focusParam[UATTree.View_sambounds]
  122. if chooseType.lower()== 'no':
  123. return self.getNoFocusedObj(option, Max_Try, findDirection, keyType, layoutUIObjParam)
  124. else:
  125. return self.toDestObj(parent, option, Max_Try, findDirection, keyType, layoutUIObjParam,fsamBounds,osamBounds)
  126. '''
  127. 传入uiautomator需要的目标组件参数,获取无聚焦属性的option对象
  128. '''
  129. def getNoFocusedObj(self,option, Max_Try, findDirection, keyType, layoutUIObjParam):
  130. count = 0
  131. directIndex = 0
  132. while(True):
  133. if count >= Max_Try and directIndex >= findDirection.__len__()-1:
  134. break
  135. time.sleep(0.1)
  136. destUIObject = self.getOptionUIObj(option, layoutUIObjParam)
  137. if destUIObject and destUIObject.exists():
  138. info(self.cls,"getNoFocusedObj","找到目标option %s"%option[UATTree.TAB_NAME],INFO)
  139. return True
  140. else:
  141. if count < Max_Try:
  142. count = count + 1
  143. elif count >= Max_Try and directIndex<findDirection.__len__() -1:
  144. count=0
  145. Max_Try *= 2
  146. directIndex = directIndex + 1
  147. self.fm.pressKeyByType(findDirection[directIndex], keyType)
  148. error(self.cls, "getNoFocusedObj", "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try)), ERROR)
  149. return False
  150. '''
  151. 传入uiautomator需要的目标组件参数和焦点框参数,用于寻找目标。
  152. '''
  153. def toDestObj(self, parent, option, Max_Try=10, findDirections=["down","up"], keyType=UATTree.Key_Event,
  154. layoutUIParam={}, fsamBounds=[],osamBounds=[]):
  155. # 按照传入的方向寻找Max_Try次,如果仍未聚焦到选中area,则按照传入方向的反方向 反向寻找 2*Max_Try 次
  156. print "toDestObj,enter:",Max_Try,findDirections,keyType,fsamBounds,osamBounds
  157. count = 0
  158. Max_Try = Max_Try
  159. directIndex = 0
  160. focusCount = 0 # 当目标和聚焦点在一个页面同时存在时,从当前聚焦点到目标的移动次数
  161. focusedBoundsPre = {u'top': 0, u'left': 0, u'right': 0, u'bottom': 0} # 上一轮聚焦点的坐标
  162. destBoundsPre = {u'top': 0, u'left': 0, u'right': 0, u'bottom': 0} # 上一轮目标的坐标
  163. while (True):
  164. if count >= Max_Try and directIndex >= findDirections.__len__()-1:
  165. break
  166. # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
  167. time.sleep(0.1)
  168. destUIObject = self.getOptionUIObj(option,layoutUIParam)
  169. focusParam = self.getFPFromOption(option)
  170. #option是否需要聚焦
  171. needFocus = True
  172. if focusParam.has_key(UATTree.FS_Type) and \
  173. focusParam[UATTree.FS_Type] == "no":
  174. needFocus = False
  175. if destUIObject and destUIObject.exists(): # 有聚焦属性的option存在不代表已聚焦,无聚焦属性的option存在即当作已聚焦
  176. try:
  177. retCode, focusedUIObject = self.getChooseUIObjP(parent, layoutUIParam,needFocus=needFocus)
  178. debug(self.cls, "toDestObj", "Parent %s 当前聚焦框retCode:%d" % (parent[UATTree.TAB_NAME],retCode), DEBUG)
  179. #如果焦点不存在,只需要判断optionView存在即可算是聚焦成功
  180. if retCode == self.Focus_Need_Not:
  181. return True
  182. #根据已获取到destUIObject和focusedUIObject,进行是否选中目标option判断,
  183. #未选中,则继续利用moveKey查找
  184. focusedBounds = focusedUIObject.info['bounds']
  185. info(self.cls,"toDestObj","当前聚焦框所在坐标:%s"%focusedBounds,INFO)
  186. destBounds = destUIObject.info['bounds']
  187. info(self.cls, "toDestObj", "已寻找%s次" % focusCount, INFO)
  188. info(self.cls,"toDestObj","目标Option %s坐标:%s"%(option[UATTree.TAB_NAME], destBounds),INFO)
  189. if self.hasFocusDest(focusedBounds, destBounds, fsamBounds=fsamBounds, osamBounds=osamBounds):
  190. info(self.cls,"toDestObj","成功聚焦到目标焦点:%s"%option[UATTree.TAB_NAME],INFO)
  191. return True
  192. # 如果往同一个方向跑了5次,聚焦坐标和目标坐标的位置都没变化,则说明目标可能为非聚焦,跑不动了
  193. if focusCount<5:
  194. direction = self.dm.getTargetDirection(focusedBounds, destBounds, findDirections)
  195. self.dm.goOneStep(self.pyU, direction, keyType)
  196. isSameFocused = self.dm.isSameBounds(focusedBoundsPre,focusedBounds) # 前一次聚焦点与当前聚焦点坐标对比
  197. isSameDest = self.dm.isSameBounds(destBoundsPre,destBounds)
  198. info(self.cls,"toDestObj","focusedBoundsPre:%s"%focusedBoundsPre,INFO)
  199. info(self.cls, "toDestObj", "focusedBounds:%s" % focusedBounds, INFO)
  200. if isSameFocused == True and isSameDest == True:
  201. focusCount += 1
  202. focusedBoundsPre = focusedBounds
  203. destBoundsPre = destBounds
  204. info(self.cls,"toDestObj.focusCount","focusCount:%s"%focusCount,INFO)
  205. continue
  206. if focusCount == 0:
  207. focusCount += 1 # 如果focusCount=0,则将当前聚焦点和目标坐标赋值给前一次
  208. focusedBoundsPre = focusedBounds
  209. destBoundsPre = destBounds
  210. info(self.cls,"toDestObj.focusCount.countStart")
  211. continue
  212. else:
  213. error(self.cls, "toDestObj", "未找到目标焦点!!!", ERROR)
  214. return False
  215. except Exception,e:
  216. info(self.cls,"toDestObj","未获取到目标/焦点对象坐标:count:%d,Max_Try:%d,directIndex:%d"%(count,Max_Try,directIndex),INFO)
  217. traceback.print_exc()
  218. # 出现控件出现一半的时候,获取控件信息会报错
  219. if count < Max_Try:
  220. count = count + 1
  221. elif count >= Max_Try and directIndex < findDirections.__len__() -1:
  222. count=0
  223. Max_Try *= 2
  224. directIndex = directIndex + 1
  225. self.fm.pressKeyByType(findDirections[directIndex], keyType)
  226. # 如果界面中没有目标文字的控件出现,则按照传入的方向寻找Max_Try次;仍然未找到 则反方向寻找2*Max_Try次
  227. else:
  228. if count < Max_Try:
  229. count = count + 1
  230. elif count >= Max_Try and directIndex<findDirections.__len__() -1:
  231. count=0
  232. Max_Try *= 2
  233. directIndex = directIndex + 1
  234. self.fm.pressKeyByType(findDirections[directIndex], keyType)
  235. error(self.cls, "toDestObj", "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try)), ERROR)
  236. return False
  237. '''
  238. 根据配置的样本焦点框和OptionView 区域坐标,计算是否聚焦
  239. :param focusedBounds 当前电视焦点框坐标
  240. :param destBounds 当前电视目标坐标
  241. :param fsamBounds 取样时的焦点框坐标
  242. :param osamBounds 取样时的目标坐标
  243. :return True/False True:焦点在目标上;False:焦点不在目标上
  244. '''
  245. def hasFocusDest(self,focusedBounds, destBounds, fsamBounds=[],osamBounds=[]):
  246. # print "hasFocusDest,focusedBounds,destBounds,fsamBounds,osamBounds:",focusedBounds, destBounds,fsamBounds,osamBounds
  247. if fsamBounds.__len__() < 1 or osamBounds.__len__()<1:
  248. return self.dm.isHasAnotherBounds(focusedBounds, destBounds)
  249. else:#在焦点框bounds特别大时,同时包含多个目标optionView时,用此方法判断是否选中。
  250. focusBounds = UIParamUtil.atxBounds2UATBounds(focusedBounds)
  251. destBounds = UIParamUtil.atxBounds2UATBounds(destBounds)
  252. print "fsamBounds,osamBounds"
  253. sdrate = self.calPointAngle(fsamBounds[0], osamBounds[0])
  254. sdLine = self.calPointLine(fsamBounds[0], osamBounds[0])
  255. print "focusBounds,destBounds"
  256. drate = self.calPointAngle(focusBounds[0],destBounds[0])
  257. dLine = self.calPointLine(focusBounds[0],destBounds[0])
  258. if abs(drate - sdrate) < 5 and abs(dLine - sdLine) < 30:
  259. return True
  260. else:
  261. return False
  262. '''
  263. 计算点p2相对点p1的角度
  264. '''
  265. def calPointAngle(self, p1, p2):
  266. angle = 0.0
  267. print "calPointAngle,p1,p2:", p1,p2
  268. dx = float(p2[0])-float(p1[0])
  269. dy = float(p2[1])-float(p1[1])
  270. print "calPointAngle,dx,dy:",dx,dy
  271. if dx == 0 and dy >= 0:
  272. return 90
  273. elif dx == 0 and dy < 0:
  274. return 180
  275. radian = math.atan(dy/dx) #计算出弧度值
  276. angle = 180 * radian/math.pi
  277. print "calPointAngle,angle,radian:",angle,radian
  278. return angle
  279. def calPointLine(self, p1,p2):
  280. print "calPointLine,p1,p2:", p1,p2
  281. dx = float(p2[0])-float(p1[0])
  282. dy = float(p2[1])-float(p1[1])
  283. line = round(math.sqrt(dx*dx + dy*dy),1)
  284. print "calPointLine,line:", line
  285. return line
  286. '''
  287. 检测option组件,在电视上是否被选中了
  288. :param option 数据字典
  289. :param layoutUIParam, parent的layout组件定位字典
  290. :param focusUIObj, 焦点组件
  291. :return -1:未进入option的页面,找不到option UIObject;0:进入了option的页面,未选中option;1 已经选中option
  292. -2:代表未找到焦点
  293. '''
  294. def checkOptionChoose(self, option, layoutUIParam, focusUIObj):
  295. optionUIObj = self.getOptionUIObj(option, layoutUIParam)
  296. if optionUIObj is None or optionUIObj.exists() is False:
  297. return -1
  298. if focusUIObj is None or focusUIObj.exists() is False:
  299. return -2
  300. focusParam = self.getFPFromOption(option)
  301. if focusParam is None:
  302. return 1
  303. try:
  304. focusedBounds = focusUIObj.info()["bounds"]
  305. destBounds = optionUIObj.info()['bounds']
  306. except Exception,e:
  307. return 0
  308. fsamBounds = focusParam[UATTree.View_sambounds]
  309. osamBounds = option[UATTree.TAB_OPTION_VIEW][UATTree.View_sambounds]
  310. if self.hasFocusDest(focusedBounds, destBounds,fsamBounds, osamBounds):
  311. return 1
  312. else:
  313. return 0
  314. def checkOptionExist(self, option, parent):
  315. # print "checkOptionExist,option:",option
  316. moveKey = parent[UATTree.TAB_MOVE_KEY]
  317. optionName = option['name']
  318. print "checkOptionExist,moveKey:", moveKey
  319. Max_Try = moveKey[UATTree.Max_Try]
  320. if Max_Try == "":
  321. Max_Try = 1
  322. else:
  323. Max_Try = int(Max_Try)
  324. Reverse_Max_Try = Max_Try * 2
  325. print "Max_Try:", Max_Try
  326. count = 0
  327. Reversecount = 0
  328. lastObj = ""
  329. while (True):
  330. if count >= Max_Try and Reversecount >= Reverse_Max_Try:
  331. break
  332. # 如果找到目标直接返回
  333. debug(self.cls,"checkOptionExist","optionView:%s"%option,DEBUG)
  334. opUIParam = UIParamUtil.setObjParam(option["optionView"])
  335. ###
  336. try:
  337. opOBJ = self.pyU.getUiObject2(opUIParam)
  338. opOBJInfo = opOBJ.info
  339. debug(self.cls,"checkOptionExist","opOBJInfo: %s"%opOBJInfo,DEBUG)
  340. break
  341. except Exception,e:
  342. opOBJ = None
  343. if count < Max_Try:
  344. flag = 1
  345. count += 1
  346. print "now count:", count
  347. else:
  348. flag = 0
  349. Reversecount += 1
  350. print "now Reversecount:", Reversecount
  351. self.runnerCommand.executeMoveKey(moveKey, flag)
  352. if opOBJ is not None and opOBJ.exists():
  353. info(self.cls, "checkOptionExist", "当前页面已找到option: %s" % optionName, INFO)
  354. return True
  355. info(self.cls, "checkOptionExist", "注意!!!当前页面未找到option: %s" % optionName, INFO)
  356. return False
  357. '''
  358. 根据option配置的焦点方式,返回当前页面焦点组件
  359. :param option: option字典
  360. :param layoutUIObj : option对应组件的根组件
  361. :return retCode,UIObject对象:reCode=0表示默认为不需要选中状态,retCode=1表示option默认为需要选中状态
  362. '''
  363. Focus_Need = 1
  364. Focus_Need_Not = 0
  365. def getChooseUIObj(self, option, layoutUIObj = None):
  366. debug(self.cls, "getChooseUIObj", "option name:"+option[UATTree.TAB_NAME],DEBUG)
  367. focusObjParam = self.getFPObjParam(option)
  368. debug(self.cls, "getChooseUIObj", "focusObjParam:"+str(focusObjParam)+"; layoutUIObj:"+str(layoutUIObj),DEBUG)
  369. if focusObjParam.__len__() <= 0:
  370. return self.Focus_Need_Not,None
  371. if layoutUIObj is None:
  372. return self.Focus_Need,self.pyU.getUiObject2(focusObjParam)
  373. else:
  374. return self.Focus_Need,layoutUIObj.child(**focusObjParam)
  375. '''
  376. 根据parent字典,检索parent是否有一个option被选中,任何一个备选中,返回option的UIObject
  377. :param parent: parent 字典
  378. :param needFocus: 目标option需要聚焦,则优先找焦点,再处理select type为no情况
  379. :return retCode,UIObject对象:reCode=0表示默认为不需要选中状态,retCode=1表示option默认为需要选中状态
  380. '''
  381. def getChooseUIObjP(self, parent, layoutUIParam, needFocus = True):
  382. if layoutUIParam.__len__() > 0:
  383. layoutUIObj = self.pyU.getUiObject2(layoutUIParam)
  384. else:
  385. layoutUIObj = None
  386. # 筛选焦点定位类型,减少重复判断
  387. focusOptionDict = self.reMuFocusOption(parent[UATTree.TAB_OPTION])
  388. debug(self.cls,"getChooseUIObjP","focusOptionDict:"+str(focusOptionDict.keys()),DEBUG)
  389. for optionName in focusOptionDict:
  390. option = focusOptionDict[optionName]
  391. retCode, uiObj = self.getChooseUIObj(option, layoutUIObj)
  392. if retCode == self.Focus_Need_Not and needFocus is False:
  393. return self.Focus_Need_Not, None
  394. elif retCode == self.Focus_Need and uiObj is not None and uiObj.exists():
  395. return retCode, uiObj
  396. return self.Focus_Need,None
  397. '''
  398. 根据parent字典,检索parent是否有一个option被选中,任何一个备选中,返回option的字典信息
  399. :param parent: parent 字典
  400. :param needFocus: 目标option需要聚焦,则优先找焦点,再处理select type为no情况
  401. :return retCode,UIObject对象:reCode=0表示默认为不需要选中状态,retCode=1表示option默认为需要选中状态
  402. '''
  403. def getChooseOptionP(self, parent, layoutUIParam, needFocus = True):
  404. if layoutUIParam.__len__() > 0:
  405. layoutUIObj = self.pyU.getUiObject2(layoutUIParam)
  406. else:
  407. layoutUIObj = None
  408. optionDict = parent[UATTree.TAB_OPTION]
  409. # 筛选焦点定位类型,减少重复判断
  410. focusOptionDict = self.reMuFocusOption(parent[UATTree.TAB_OPTION])
  411. debug(self.cls,"getChooseUIObjP","focusOptionDict:"+str(focusOptionDict.keys()),DEBUG)
  412. # 是否确认当前聚焦optionName的标识
  413. # 用任意一option,获取当前聚焦的uiobj
  414. optionName = focusOptionDict.keys()[0]
  415. option = focusOptionDict[optionName]
  416. retCode, choosedObj = self.getChooseUIObj(option, layoutUIObj)
  417. if retCode == self.Focus_Need_Not and needFocus is False:
  418. return self.Focus_Need_Not, None
  419. elif retCode == self.Focus_Need and choosedObj is not None and choosedObj.exists():
  420. for optionName in optionDict:
  421. option = optionDict[optionName]
  422. destUIParam = UIParamUtil.setObjParam(option[UATTree.TAB_OPTION_VIEW])
  423. destObj = self.pyU.getUiObject2(destUIParam)
  424. if destObj.exists():
  425. choosedBound = choosedObj.info['bounds']
  426. destBound = destObj.info['bounds']
  427. if self.dm.isHasAnotherBounds(choosedBound, destBound):
  428. return self.Focus_Need, option
  429. return self.Focus_Need,None
  430. def reMuFocusOption(self, optionDict):
  431. retDict = {}
  432. for optionName in optionDict:
  433. option = optionDict[optionName]
  434. focusObjParam = self.getFPObjParam(option)
  435. if retDict.__len__() == 0:
  436. retDict[optionName] = option
  437. continue
  438. isSame = False
  439. for retName in retDict:
  440. retOption = optionDict[retName]
  441. retFocusObjParam = self.getFPObjParam(retOption)
  442. if UIParamUtil.cmpObjParam(focusObjParam, retFocusObjParam):
  443. isSame = True
  444. break
  445. if isSame is False:
  446. retDict[optionName] = option
  447. return retDict
  448. '''
  449. 根据option和layoutUIParam参数,获取option UIObject对象
  450. layoutUIParam参数有效,则在layout里查找子组件option,否则全界面查找子组件。
  451. '''
  452. def getOptionUIObj(self, option, layoutUIParam):
  453. debug(self.cls, "getOptionUIObj","OptionView:"+str(option[UATTree.TAB_OPTION_VIEW]),DEBUG)
  454. destUIParam = UIParamUtil.setObjParam(option[UATTree.TAB_OPTION_VIEW])
  455. debug(self.cls, "getOptionUIObj", "destUIParam:" + str(destUIParam), DEBUG)
  456. destUITextExist = False
  457. try:
  458. destUIText = destUIParam['text']
  459. destUITextExist = True
  460. except Exception, e:
  461. info(self.cls, "getOptionUIObj", "目标对象%s的optionView无text属性"%option[UATTree.TAB_NAME], INFO)
  462. if destUITextExist is True:
  463. #####################
  464. if type(destUIParam['text']) is type([]):
  465. destUIObjectExist = False
  466. tempTextList = destUIParam['text']
  467. txtCount = 0
  468. for txt in tempTextList:
  469. destUIParam['text'] = txt
  470. uix = self.pyU.dump_hierarchy()
  471. if txt not in uix:
  472. continue
  473. if layoutUIParam.__len__() > 0:
  474. layoutUIObj = self.pyU.getUiObject2(layoutUIParam)
  475. try:
  476. destUIObject = layoutUIObj.child(**destUIParam)
  477. destUIObjectInfo = destUIObject.info
  478. destUIObjectExist = True
  479. info(self.cls, "getOptionUIObj", "文本%s对应的option对象已找到" % txt, INFO)
  480. except Exception, e:
  481. nextText = tempTextList[txtCount + 1]
  482. error(self.cls, "getOptionUIObj", "文本%s对应的option对象未找到,匹配下一个文本%s" % (txt, nextText), ERROR)
  483. if destUIObjectExist is True:
  484. break
  485. else:
  486. try:
  487. destUIObject = self.pyU.getUiObject2(destUIParam)
  488. destUIObjectInfo = destUIObject.info
  489. destUIObjectExist = True
  490. info(self.cls, "getOptionUIObj", "文本%s对应的option对象已找到" % txt, INFO)
  491. except Exception, e:
  492. nextText = tempTextList[txtCount + 1]
  493. error(self.cls, "getOptionUIObj", "文本%s对应的option对象未找到,匹配下一个文本%s" % (txt, nextText), ERROR)
  494. if destUIObjectExist is True:
  495. break
  496. txtCount += 1
  497. else:
  498. if layoutUIParam.__len__() > 0:
  499. layoutUIObj = self.pyU.getUiObject2(layoutUIParam)
  500. destUIObject = layoutUIObj.child(**destUIParam)
  501. else:
  502. destUIObject = self.pyU.getUiObject2(destUIParam)
  503. #########################
  504. else:
  505. if layoutUIParam.__len__() > 0:
  506. layoutUIObj = self.pyU.getUiObject2(layoutUIParam)
  507. destUIObject = layoutUIObj.child(**destUIParam)
  508. else:
  509. destUIObject = self.pyU.getUiObject2(destUIParam)
  510. return destUIObject
  511. '''
  512. 检测parent,在电视上是否被选中了。一个option被选中,表示选中
  513. :param option 数据字典
  514. :return
  515. -3:代表UIView判断未通过;
  516. -2:代表选中了parent,但未找到焦点;
  517. -1:未进入parent的页面,找不到parent layout;
  518. 0:进入了parent的页面,未选中parent;
  519. 1:已经选中parent
  520. '''
  521. def checkParentChoose(self, parent):
  522. debug(self.cls, "checkParentChoose", "parent:" + parent[UATTree.TAB_NAME], DEBUG)
  523. chooseTypeDict = {}
  524. layoutParam = parent[UATTree.TAB_LAYOUT]
  525. layoutUIParam = UIParamUtil.setObjParam(layoutParam)
  526. layoutResId = layoutParam[UATTree.View_ID]
  527. uiView = parent[UATTree.TAB_UI_VIEW]
  528. uiViewResId = uiView[UATTree.View_ID]
  529. uiViewText = uiView[UATTree.View_Text]
  530. uiViewDesc = uiView[UATTree.View_Desc]
  531. # print "checkParentChoose,layoutUIParam:",layoutUIParam
  532. if layoutResId == "" and uiViewResId == "" and uiViewText == "" and uiViewDesc == "":
  533. debug(self.cls, "checkParentChoose",
  534. "Warning:Parent %s的Layout resId和UIView信息获取失败!!请注意检查UATree文件!!!" % parent[UATTree.TAB_NAME], DEBUG)
  535. return -1
  536. elif layoutUIParam.__len__() > 0:
  537. # 如果存在UIView信息,则先判断UIView
  538. isExist = self.checkUIViewExist(uiView)
  539. if isExist is False:
  540. info(self.cls, "checkParentChoose", "当前页面不存在Parent:%s的UIView组件,判断该界面非此parent" % parent[UATTree.TAB_NAME],
  541. INFO)
  542. return -3
  543. else:
  544. debug(self.cls, "checkParentChoose", "已识别出Parent:%s的UIView组件" % parent[UATTree.TAB_NAME], DEBUG)
  545. # 判断Layout是否存在
  546. layoutUIObj = self.pyU.getUiObject2(layoutUIParam)
  547. if layoutUIObj is None or layoutUIObj.exists() is False:
  548. info(self.cls, "checkParentChoose", "parent %s layout 不存在 "%parent[UATTree.TAB_NAME], INFO)
  549. return -1
  550. debug(self.cls, "checkParentChoose", "parent %s layout 存在"%parent[UATTree.TAB_NAME], DEBUG)
  551. # 获取焦点组件,判断是否在layout中
  552. retCode, focusObj = self.getChooseUIObjP(parent, layoutUIParam, needFocus=False)
  553. if retCode == self.Focus_Need_Not:
  554. debug(self.cls, "checkParentChoose",
  555. "已找到目标parent %s,不需要选中。" % (parent['name']), DEBUG)
  556. elif focusObj is not None and focusObj.exists():
  557. debug(self.cls, "checkParentChoose",
  558. "已找到目标parent %s,焦点在Layout中。" % (parent['name']), DEBUG)
  559. else:
  560. info(self.cls, "checkParentChoose",
  561. "已找到目标parent %s,但是焦点不在Layout中。" % (parent['name']), INFO)
  562. return -2
  563. # 判断parent中存在一个option,则标识parent被选中。注意:为了快速消失界面相应
  564. if layoutParam[UATTree.Layout_Limit] <> 1:
  565. layoutUIParam = {}
  566. optionUIObj = None
  567. optionExist = False
  568. for optionName in parent["option"]:
  569. option = parent["option"][optionName]
  570. ret = self.checkOptionExist(option,parent)
  571. if ret is True:
  572. info(self.cls, "checkParentChoose",
  573. "已找到目标parent %s,识别出该parent下的option %s。" % (parent['name'], option['name']),
  574. INFO)
  575. return 1
  576. info(self.cls, "checkParentChoose",
  577. "已找到目标parent %s,但是parent下的option未被发现。" % (parent['name']), INFO)
  578. return 0
  579. else:
  580. isExist = self.checkUIViewExist(uiView)
  581. if not isExist:
  582. return -3
  583. else:
  584. info(self.cls, "checkParentChoose",
  585. "识别出parent %s的UIView参数,判断处于该界面中" % (parent['name']), INFO)
  586. return 1
  587. '''
  588. 检测某个弹窗是否存在。
  589. 弹窗相关的参数放在UIView中配置。
  590. 当存在resId参数时,使用resId获取对象并获取文本,再与text做比较;
  591. 当不存在resId参数时,使用text直接获取对象,判断对象是否存在。
  592. 与checkParentChoose判断不一致,做特殊处理。
  593. :return 整型:0代表不存在,1代表存在
  594. '''
  595. def checkDialogExist(self, dialog):
  596. debug(self.cls, "checkDialogExist", "dialog:" + dialog["name"], DEBUG)
  597. dialogText = dialog[UATTree.TAB_UI_VIEW][UATTree.View_Text]
  598. dialogResId = dialog[UATTree.TAB_UI_VIEW][UATTree.View_ID]
  599. # print "checkDialogExist.dialogText:", dialogText
  600. # print "checkDialogExist.dialogResId:", dialogResId
  601. if dialogResId != "":
  602. textObj = self.pyU.getUiObject(resourceId=dialogResId)
  603. if textObj.exists:
  604. objText = textObj.info['text']
  605. # print "checkDialogExist.objText:", objText
  606. if dialogText in objText:
  607. return 1
  608. else:
  609. return 0
  610. else:
  611. return 0
  612. else:
  613. textObj = self.pyU.getUiObject(text=dialogText)
  614. if textObj.exists:
  615. return 1
  616. else:
  617. return 0
  618. def checkUIViewExist(self, uiView):
  619. #uiview未配置默认为检测通过
  620. if uiView.__len__() == 0:
  621. return True
  622. uiviewObjParam = UIParamUtil.setObjParam(uiView)
  623. uiViewObj = self.pyU.getUiObject2(uiviewObjParam)
  624. if uiViewObj is None or uiViewObj.exists is False:
  625. return False
  626. else:
  627. return True
  628. def moveToCheckedRedioButton(self, fsParam, findDirection="down", keyType=UATTree.Key_Event, maxTry=20):
  629. count = 0
  630. Reversecount = 0
  631. tryCount = 0
  632. while(True):
  633. param={"checked":"true"}
  634. checkedObj = self.pyU.getUiObject2(param)
  635. if not checkedObj.exists():
  636. if count < maxTry:
  637. self.fm.pressKeyByType(findDirection[1], keyType)
  638. count += 1
  639. continue
  640. else:
  641. Reversecount = Reversecount + 1
  642. self.fm.pressKeyByType(self.fm.ReverseDirctionDict[findDirection], keyType)
  643. continue
  644. choosedObj = self.pyU.getUiObject2(fsParam)
  645. if not choosedObj.exists():
  646. count += 1
  647. continue
  648. choosedBounds = choosedObj.info['bounds']
  649. checkedBounds = checkedObj.info['bounds']
  650. if self.dm.isHasAnotherBounds(choosedBounds, checkedBounds):
  651. info(self.cls, "moveToCheckedRedioButton", "已聚焦至目标组件!!!", INFO)
  652. return True, choosedObj
  653. else:
  654. direction = self.dm.getTargetDirection(choosedBounds, checkedBounds)
  655. print "目标方位:",direction
  656. self.dm.goOneStep(self.pyU, direction, keyType)
  657. tryCount += 1
  658. if tryCount >= maxTry:
  659. error(self.cls, "moveToCheckedRedioButton", "已尝试至最大次数%s次,仍未能聚焦至目标组件!!!"%maxTry, error)
  660. return False, choosedObj
  661. if Reversecount >= maxTry:
  662. error(self.cls, "moveToCheckedRedioButton", "已尝试至最大次数%s次,仍未能找到目标组件!!!"%maxTry, error)
  663. return False, choosedObj
  664. if __name__ == "__main__":
  665. uatPathManage = UATPathManage()
  666. pyU = PyUIAutomator()
  667. dm = DirectionManageAndroid()
  668. fm = FocusManageAndroid(pyU, dm)
  669. # runnerCmd = UATRunnerCommand(uatPathManage, pyU, dm, fm)
  670. # focusCmd = FocusCommand(runnerCmd)
  671. # ret = focusCmd.calPointAngle([0,0],[244,151])
  672. # ret = focusCmd.calPointAngle([244,151],[107,641])
  673. # focusCmd.strToBounds('[801,116][1280,180]')
  674. # option = focusCmd.runnerCommand.uatPathManage.uatData.getOption("av_devices_settings")
  675. # parent = focusCmd.runnerCommand.uatPathManage.uatData.getParentByOption(option)
  676. # focusCmd.focusOptionView(parent, option)
  677. # print "dump_hierarchy 0:",time.time()
  678. # print focusCmd.pyU.dump_hierarchy()
  679. # print "dump_hierarchy 1:",time.time()
  680. # uiobjg = focusCmd.pyU.getUiObject()