mirror of
https://github.com/frida/frida-tools.git
synced 2026-11-07 09:35:59 -10:00
ps: Retry without icons when icon loading fails
Some devices fail the whole full-scope enumeration when an app icon cannot be loaded, e.g. Android raising Resources$NotFoundException for sym_def_app_icon. Retry with the minimal scope and warn, so the listing still works. Refs frida/frida#3762
This commit is contained in:
1 parent
735a2770ce
commit
280fb9e2c8
2 files changed
+70
-2
No files matched your search
+22
-2
@@ -79,7 +79,11 @@ def main() -> None:
|
||||
|
||||
try:
|
||||
assert self._device is not None
|
||||
processes = self._device.enumerate_processes(scope=scope)
|
||||
processes = _enumerate_with_icon_fallback(
|
||||
self._device.enumerate_processes,
|
||||
scope,
|
||||
lambda e: self._log("warning", f"Unable to load app icons ({e}), listing without them"),
|
||||
)
|
||||
except Exception as e:
|
||||
self._update_status(f"Failed to enumerate processes: {e}")
|
||||
self._exit(1)
|
||||
@@ -128,7 +132,11 @@ def main() -> None:
|
||||
|
||||
try:
|
||||
assert self._device is not None
|
||||
applications = self._device.enumerate_applications(scope=scope)
|
||||
applications = _enumerate_with_icon_fallback(
|
||||
self._device.enumerate_applications,
|
||||
scope,
|
||||
lambda e: self._log("warning", f"Unable to load app icons ({e}), listing without them"),
|
||||
)
|
||||
except Exception as e:
|
||||
self._update_status(f"Failed to enumerate applications: {e}")
|
||||
self._exit(1)
|
||||
@@ -287,6 +295,18 @@ def main() -> None:
|
||||
app.run()
|
||||
|
||||
|
||||
def _enumerate_with_icon_fallback(enumerate_fn, scope, warn):
|
||||
if scope != "full":
|
||||
return enumerate_fn(scope=scope)
|
||||
|
||||
try:
|
||||
return enumerate_fn(scope="full")
|
||||
except Exception as e:
|
||||
result = enumerate_fn(scope="minimal")
|
||||
warn(e)
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import unittest
|
||||
|
||||
from frida_tools.ps import _enumerate_with_icon_fallback
|
||||
|
||||
|
||||
class TestPSEnumerationFallback(unittest.TestCase):
|
||||
def test_full_scope_failure_is_retried_without_icons(self):
|
||||
device = FakeDevice(fail_scopes={"full"})
|
||||
warnings = []
|
||||
processes = _enumerate_with_icon_fallback(device.enumerate_processes, "full", warnings.append)
|
||||
self.assertEqual(processes, ["init"])
|
||||
self.assertEqual(device.calls, ["full", "minimal"])
|
||||
self.assertEqual(len(warnings), 1)
|
||||
self.assertIn("could not load icons", str(warnings[0]))
|
||||
|
||||
def test_full_scope_success_is_returned_as_is(self):
|
||||
device = FakeDevice(fail_scopes=set())
|
||||
warnings = []
|
||||
processes = _enumerate_with_icon_fallback(device.enumerate_processes, "full", warnings.append)
|
||||
self.assertEqual(processes, ["init"])
|
||||
self.assertEqual(device.calls, ["full"])
|
||||
self.assertEqual(warnings, [])
|
||||
|
||||
def test_minimal_scope_failure_is_propagated(self):
|
||||
device = FakeDevice(fail_scopes={"minimal"})
|
||||
with self.assertRaises(RuntimeError):
|
||||
_enumerate_with_icon_fallback(device.enumerate_processes, "minimal", lambda e: None)
|
||||
self.assertEqual(device.calls, ["minimal"])
|
||||
|
||||
def test_failure_that_is_not_about_icons_is_not_reported_as_one(self):
|
||||
device = FakeDevice(fail_scopes={"full", "minimal"})
|
||||
warnings = []
|
||||
with self.assertRaises(RuntimeError):
|
||||
_enumerate_with_icon_fallback(device.enumerate_processes, "full", warnings.append)
|
||||
self.assertEqual(device.calls, ["full", "minimal"])
|
||||
self.assertEqual(warnings, [])
|
||||
|
||||
|
||||
class FakeDevice:
|
||||
def __init__(self, fail_scopes):
|
||||
self.fail_scopes = fail_scopes
|
||||
self.calls = []
|
||||
|
||||
def enumerate_processes(self, scope="minimal"):
|
||||
self.calls.append(scope)
|
||||
if scope in self.fail_scopes:
|
||||
raise RuntimeError(f"could not load icons for {scope}")
|
||||
return ["init"]
|
||||
Reference in new issue
Block a user