From a9b8034aade6aa8c0bddda143da1ee20431b95b7 Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Tue, 18 Feb 2025 23:59:21 -0500 Subject: [PATCH 1/3] Fix #6 uninstall device admin async Add the check for device admin to `device_async.py` `uninstall()` Fix endless loop if disabling the user either fails, or does not fix the inability to uninstall --- ppadb/device.py | 37 +++++++++++++++++++++++-------------- ppadb/device_async.py | 33 +++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/ppadb/device.py b/ppadb/device.py index a7d7dd4..eda1a93 100644 --- a/ppadb/device.py +++ b/ppadb/device.py @@ -165,19 +165,28 @@ def is_installed(self, package): return False def uninstall(self, package): - result = self.shell("pm uninstall {}".format(package)) + attempts_remaining = 2 + while attempts_remaining > 0: + attempts_remaining -= 1 - m = re.search(self.UNINSTALL_RESULT_PATTERN, result) + result = self.shell("pm uninstall {}".format(package)) + m = re.search(self.UNINSTALL_RESULT_PATTERN, result) - if m and m.group(1) == "Success": - return True - elif m: - logger.error(m.group(1)) - if "DELETE_FAILED_DEVICE_POLICY_MANAGER" in m.group(1): - logger.info("App is device-admin, calling disable-user") - self.shell("pm disable-user {}".format(package)) - return self.uninstall(package) - return False - else: - logger.error("There is no message after uninstalling") - return False + if m and m.group(1) == "Success": + return True + elif m: + if ( + "DELETE_FAILED_DEVICE_POLICY_MANAGER" in m.group(1) + and attempts_remaining > 0 + ): + logger.warn(m.group(1)) + logger.info("App is device-admin, calling disable-user") + self.shell("pm disable-user {}".format(package)) + else: + logger.error(m.group(1)) + return False + else: + logger.error("There is no message after uninstalling") + return False + + return False diff --git a/ppadb/device_async.py b/ppadb/device_async.py index 26c23de..992557e 100644 --- a/ppadb/device_async.py +++ b/ppadb/device_async.py @@ -146,15 +146,28 @@ async def install( await self.shell("rm -f {}".format(dest)) async def uninstall(self, package): - result = await self.shell("pm uninstall {}".format(package)) + attempts_remaining = 2 + while attempts_remaining > 0: + attempts_remaining -= 1 - m = re.search(self.UNINSTALL_RESULT_PATTERN, result) + result = await self.shell("pm uninstall {}".format(package)) + m = re.search(self.UNINSTALL_RESULT_PATTERN, result) - if m and m.group(1) == "Success": - return True - elif m: - logger.error(m.group(1)) - return False - else: - logger.error("There is no message after uninstalling") - return False + if m and m.group(1) == "Success": + return True + elif m: + if ( + "DELETE_FAILED_DEVICE_POLICY_MANAGER" in m.group(1) + and attempts_remaining > 0 + ): + logger.warn(m.group(1)) + logger.info("App is device-admin, calling disable-user") + await self.shell("pm disable-user {}".format(package)) + else: + logger.error(m.group(1)) + return False + else: + logger.error("There is no message after uninstalling") + return False + + return False From 442c8be4a032e53551f11d4c1fd358b2e9f94522 Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Wed, 19 Feb 2025 00:12:04 -0500 Subject: [PATCH 2/3] Add missing requirement for async --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 274fbc7..0e59c78 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ pytest Exscript +aiofiles >= 0.4.0 From 4c867f75a3bd6f759aa68c6847be857d311f04a1 Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Wed, 19 Feb 2025 00:27:52 -0500 Subject: [PATCH 3/3] Don't install extra packages --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 46b89f2..37e5705 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -10,7 +10,7 @@ services: environment: - PYTHONPATH=/code - PYTHONUNBUFFERED=0 - command: sh -c "pip install -r requirements.txt;pip install 'Exscript';py.test test -s -v --junit-xml test_result.xml;pip install 'aiofiles>=0.4.0';py.test test_async -s -v --junit-xml test_result_async.xml;" + command: sh -c "pip install -r requirements.txt;py.test test -s -v --junit-xml test_result.xml;py.test test_async -s -v --junit-xml test_result_async.xml;" emulator: image: swind/android-emulator:android_28