Skip to content

Commit 0031134

Browse files
authored
Merge pull request #23 from e790a8/master
fix: init agent and windows shell
2 parents d478c4d + 6a95d5c commit 0031134

File tree

4 files changed

+127
-49
lines changed

4 files changed

+127
-49
lines changed

hmdriver2/_client.py

Lines changed: 52 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# -*- coding: utf-8 -*-
2-
2+
import re
33
import socket
44
import json
55
import time
66
import os
7+
import glob
78
import typing
89
import subprocess
9-
import hashlib
1010
from datetime import datetime
1111
from functools import cached_property
1212

@@ -18,6 +18,8 @@
1818

1919
UITEST_SERVICE_PORT = 8012
2020
SOCKET_TIMEOUT = 20
21+
ASSETS_PATH = os.path.join(os.path.dirname(__file__), "assets")
22+
AGENT_CLEAR_PATH = ["app", "commons-", "agent", "libagent_antry"]
2123

2224

2325
class HmClient:
@@ -169,39 +171,53 @@ def _create_hdriver(self) -> DriverData:
169171
def _init_so_resource(self):
170172
"Initialize the agent.so resource on the device."
171173

172-
logger.debug("init the agent.so resource on the device.")
173-
174-
def __get_so_local_path() -> str:
175-
current_path = os.path.realpath(__file__)
176-
return os.path.join(os.path.dirname(current_path), "assets", "uitest_agent_v1.1.0.so")
177-
178-
def __check_device_so_file_exists() -> bool:
179-
"""Check if the agent.so file exists on the device."""
180-
command = "[ -f /data/local/tmp/agent.so ] && echo 'so exists' || echo 'so not exists'"
181-
result = self.hdc.shell(command).output.strip()
182-
return "so exists" in result
183-
184-
def __get_remote_md5sum() -> str:
185-
"""Get the MD5 checksum of the file on the device."""
186-
command = "md5sum /data/local/tmp/agent.so"
187-
data = self.hdc.shell(command).output.strip()
188-
return data.split()[0]
189-
190-
def __get_local_md5sum(f: str) -> str:
191-
"""Calculate the MD5 checksum of a local file."""
192-
hash_md5 = hashlib.md5()
193-
with open(f, "rb") as f:
194-
for chunk in iter(lambda: f.read(4096), b""):
195-
hash_md5.update(chunk)
196-
return hash_md5.hexdigest()
197-
198-
local_path = __get_so_local_path()
199-
remote_path = "/data/local/tmp/agent.so"
200-
201-
if __check_device_so_file_exists() and __get_local_md5sum(local_path) == __get_remote_md5sum():
202-
return
203-
self.hdc.send_file(local_path, remote_path)
204-
self.hdc.shell(f"chmod +x {remote_path}")
174+
file_postfix = ".so"
175+
device_agent_path = "/data/local/tmp/agent.so"
176+
arch_info = self.hdc.shell("file /system/bin/uitest").output.strip()
177+
if "x86_64" in arch_info:
178+
file_postfix = ".x86_64_so"
179+
local_path = ""
180+
local_ver = "0.0.0"
181+
for agent_file in glob.glob(os.path.join(ASSETS_PATH, "uitest_agent*so")):
182+
file_name = os.path.split(agent_file)[1]
183+
if not agent_file.endswith(file_postfix):
184+
continue
185+
matcher = re.search(r'\d{1,3}[.]\d{1,3}[.]\d{1,3}', file_name)
186+
if not matcher:
187+
continue
188+
ver = matcher.group()[0]
189+
if ver.split('.') > local_ver.split('.'):
190+
local_ver, local_path = ver, agent_file
191+
device_ver_info = self.hdc.shell(f"cat {device_agent_path} | grep -a UITEST_AGENT_LIBRARY").output.strip()
192+
matcher = re.search(r'\d{1,3}[.]\d{1,3}[.]\d{1,3}', device_ver_info)
193+
device_ver = matcher.group(0) if matcher else "0.0.0"
194+
logger.debug(f"local agent version {local_ver}, device agent version {device_ver}")
195+
if device_ver.split('.') < local_ver.split('.'):
196+
logger.debug(f"start update agent, path is {local_path}")
197+
self._kill_uitest_service()
198+
for file in AGENT_CLEAR_PATH:
199+
self.hdc.shell(f"rm /data/local/tmp/{file}*")
200+
self.hdc.send_file(local_path, device_agent_path)
201+
self.hdc.shell(f"chmod +x {device_agent_path}")
202+
logger.debug("Update agent finish.")
203+
else:
204+
logger.debug("Device agent is up to date!")
205+
206+
def get_devicetest_proc_pid(self):
207+
proc_pids = []
208+
result = self.hdc.shell("ps -ef").output.strip()
209+
lines = result.splitlines()
210+
filtered_lines = [line for line in lines if 'uitest' in line and 'singleness' in line]
211+
for line in filtered_lines:
212+
if 'uitest start-daemon singleness' not in line:
213+
continue
214+
proc_pids.append(line.split()[1])
215+
return proc_pids
216+
217+
def _kill_uitest_service(self):
218+
for pid in self.get_devicetest_proc_pid():
219+
self.hdc.shell(f"kill -9 {pid}")
220+
logger.debug(f"Killed uitest process with PID {pid}")
205221

206222
def _restart_uitest_service(self):
207223
"""
@@ -213,17 +229,7 @@ def _restart_uitest_service(self):
213229
shell 44416 1 2 11:03:42 ? 00:00:01 uitest start-daemon com.hmtest.uitest@4x9@1"
214230
"""
215231
try:
216-
result = self.hdc.shell("ps -ef").output.strip()
217-
lines = result.splitlines()
218-
filtered_lines = [line for line in lines if 'uitest' in line and 'singleness' in line]
219-
220-
for line in filtered_lines:
221-
if 'uitest start-daemon singleness' in line:
222-
parts = line.split()
223-
pid = parts[1]
224-
self.hdc.shell(f"kill -9 {pid}")
225-
logger.debug(f"Killed uitest process with PID {pid}")
226-
232+
self._kill_uitest_service()
227233
self.hdc.shell("uitest start-daemon singleness")
228234
time.sleep(.5)
229235

1.37 MB
Binary file not shown.

hmdriver2/driver.py

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,11 @@ def _invoke(self, api: str, args: List = []) -> HypiumResponse:
8383
return self._client.invoke(api, this="Driver#0", args=args)
8484

8585
@delay
86-
def start_app(self, package_name: str, page_name: str = "MainAbility"):
86+
def start_app(self, package_name: str, page_name: str = ''):
87+
page_name = page_name or self.get_app_main_ability(package_name).get('name', 'MainAbility')
8788
self.hdc.start_app(package_name, page_name)
8889

89-
def force_start_app(self, package_name: str, page_name: str = "MainAbility"):
90+
def force_start_app(self, package_name: str, page_name: str = ""):
9091
self.go_home()
9192
self.stop_app(package_name)
9293
self.start_app(package_name, page_name)
@@ -148,6 +149,74 @@ def get_app_info(self, package_name: str) -> Dict:
148149
logger.error(f"An error occurred:{e}")
149150
return app_info
150151

152+
def get_app_abilities(self, package_name: str) -> List[Dict]:
153+
"""
154+
Get the abilities of an application.
155+
156+
157+
Args:
158+
package_name (str): The package name of the application to retrieve information for.
159+
160+
Returns:
161+
List[Dict]: A list of dictionaries containing the abilities of the application.
162+
"""
163+
result = []
164+
app_info = self.get_app_info(package_name)
165+
hap_module_infos = app_info.get("hapModuleInfos")
166+
main_entry = app_info.get("mainEntry")
167+
for hap_module_info in hap_module_infos:
168+
# 尝试读取moduleInfo
169+
try:
170+
ability_infos = hap_module_info.get("abilityInfos")
171+
module_main = hap_module_info["mainAbility"]
172+
except Exception as e:
173+
logger.warning(f"Fail to parse moduleInfo item, {repr(e)}")
174+
continue
175+
# 尝试读取abilityInfo
176+
for ability_info in ability_infos:
177+
try:
178+
is_launcher_ability = False
179+
skills = ability_info['skills']
180+
if len(skills) > 0 or "action.system.home" in skills[0]["actions"]:
181+
is_launcher_ability = True
182+
icon_ability_info = {
183+
"name": ability_info["name"],
184+
"moduleName": ability_info["moduleName"],
185+
"moduleMainAbility": module_main,
186+
"mainModule": main_entry,
187+
"isLauncherAbility": is_launcher_ability
188+
}
189+
result.append(icon_ability_info)
190+
except Exception as e:
191+
logger.warning(f"Fail to parse ability_info item, {repr(e)}")
192+
continue
193+
logger.debug(f"all abilities: {result}")
194+
return result
195+
196+
def get_app_main_ability(self, package_name: str) -> Dict:
197+
"""
198+
Get the main ability of an application.
199+
200+
Args:
201+
package_name (str): The package name of the application to retrieve information for.
202+
203+
Returns:
204+
Dict: A dictionary containing the main ability of the application.
205+
206+
"""
207+
if not (abilities := self.get_app_abilities(package_name)):
208+
return {}
209+
for item in abilities:
210+
score = 0
211+
if (name := item["name"]) and name == item["moduleMainAbility"]:
212+
score += 1
213+
if (module_name := item["moduleName"]) and module_name == item["mainModule"]:
214+
score += 1
215+
item["score"] = score
216+
abilities.sort(key=lambda x: (not x["isLauncherAbility"], -x["score"]))
217+
logger.debug(f"main ability: {abilities[0]}")
218+
return abilities[0]
219+
151220
@cached_property
152221
def toast_watcher(self):
153222

hmdriver2/hdc.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# -*- coding: utf-8 -*-
2-
32
import tempfile
43
import json
54
import uuid
@@ -115,6 +114,10 @@ def recv_file(self, rpath: str, lpath: str):
115114
return result
116115

117116
def shell(self, cmd: str, error_raise=True) -> CommandResult:
117+
if cmd[0] != '\"':
118+
cmd = "\"" + cmd
119+
if cmd[-1] != '\"':
120+
cmd += '\"'
118121
result = _execute_command(f"{self.hdc_prefix} -t {self.serial} shell {cmd}")
119122
if result.exit_code != 0 and error_raise:
120123
raise HdcError("HDC shell error", f"{cmd}\n{result.output}\n{result.error}")

0 commit comments

Comments
 (0)