From 484e6dbb879cb59d0d3feab53884c64e2bf3b820 Mon Sep 17 00:00:00 2001 From: Hongyi Zhang Date: Thu, 7 May 2020 10:03:46 -0700 Subject: [PATCH] Start rebootPromptAndWipeUserData from a separate thread in RescueParty Call rebootPromptAndWipeUserData from currently thread in RescueParty will cause a deadlock in PackageWatchdog when shutting down device, if the reset is triggerred by PackageWatchdog. Forking a separate thread to execute it to release the lock. Test: Trigger final level of rescue on a local device, and now can successfully shutdown and boot into recovery mode. Bug: 155780451 Change-Id: I3a901a469e172252deac9f6e4f1f2ab7a455fa58 --- .../java/com/android/server/RescueParty.java | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java index bfcde97d6c916..829fca66ec0da 100644 --- a/services/core/java/com/android/server/RescueParty.java +++ b/services/core/java/com/android/server/RescueParty.java @@ -253,10 +253,7 @@ public class RescueParty { logCriticalInfo(Log.DEBUG, "Finished rescue level " + levelToString(level)); } catch (Throwable t) { - final String msg = ExceptionUtils.getCompleteMessage(t); - EventLogTags.writeRescueFailure(level, msg); - logCriticalInfo(Log.ERROR, - "Failed rescue level " + levelToString(level) + ": " + msg); + logRescueException(level, t); } } @@ -274,11 +271,31 @@ public class RescueParty { resetAllSettings(context, Settings.RESET_MODE_TRUSTED_DEFAULTS, failedPackage); break; case LEVEL_FACTORY_RESET: - RecoverySystem.rebootPromptAndWipeUserData(context, TAG); + // Request the reboot from a separate thread to avoid deadlock on PackageWatchdog + // when device shutting down. + Runnable runnable = new Runnable() { + @Override + public void run() { + try { + RecoverySystem.rebootPromptAndWipeUserData(context, TAG); + } catch (Throwable t) { + logRescueException(level, t); + } + } + }; + Thread thread = new Thread(runnable); + thread.start(); break; } } + private static void logRescueException(int level, Throwable t) { + final String msg = ExceptionUtils.getCompleteMessage(t); + EventLogTags.writeRescueFailure(level, msg); + logCriticalInfo(Log.ERROR, + "Failed rescue level " + levelToString(level) + ": " + msg); + } + private static int mapRescueLevelToUserImpact(int rescueLevel) { switch(rescueLevel) { case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS: