Making RescueParty reboot and factory reset synchronous.
PackageWatchdog.dump() waits on a lock which is held when RescueParty attempts remediation, making the dump not use the lock in those cases.
Bug: 328203835
Change-Id: I69aa3ef11a435d10479b8a63060699ff01647ebc
Test: presubmit
Flag: android.crashrecovery.flags.synchronous_reboot_in_rescue_party
diff --git a/packages/CrashRecovery/aconfig/flags.aconfig b/packages/CrashRecovery/aconfig/flags.aconfig
index 52e0cbb..c6c49e0 100644
--- a/packages/CrashRecovery/aconfig/flags.aconfig
+++ b/packages/CrashRecovery/aconfig/flags.aconfig
@@ -39,3 +39,10 @@
bug: "289203818"
is_fixed_read_only: true
}
+
+flag {
+ name: "synchronous_reboot_in_rescue_party"
+ namespace: "modularization"
+ description: "Makes reboot and factory reset synchronous in RescueParty"
+ bug: "328203835"
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 682eb76..9060250 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -1292,6 +1292,16 @@
/** Dump status of every observer in mAllObservers. */
public void dump(@NonNull PrintWriter pw) {
+ if (Flags.synchronousRebootInRescueParty() && RescueParty.isRecoveryTriggeredReboot()) {
+ dumpInternal(pw);
+ } else {
+ synchronized (mLock) {
+ dumpInternal(pw);
+ }
+ }
+ }
+
+ private void dumpInternal(@NonNull PrintWriter pw) {
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
ipw.println("Package Watchdog status");
ipw.increaseIndent();
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index a6e21fc..ada1953 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -631,7 +631,8 @@
// Request the reboot from a separate thread to avoid deadlock on PackageWatchdog
// when device shutting down.
setRebootProperty(true);
- Runnable runnable = () -> {
+
+ if (Flags.synchronousRebootInRescueParty()) {
try {
PowerManager pm = context.getSystemService(PowerManager.class);
if (pm != null) {
@@ -640,9 +641,20 @@
} catch (Throwable t) {
logRescueException(level, failedPackage, t);
}
- };
- Thread thread = new Thread(runnable);
- thread.start();
+ } else {
+ Runnable runnable = () -> {
+ try {
+ PowerManager pm = context.getSystemService(PowerManager.class);
+ if (pm != null) {
+ pm.reboot(TAG);
+ }
+ } catch (Throwable t) {
+ logRescueException(level, failedPackage, t);
+ }
+ };
+ Thread thread = new Thread(runnable);
+ thread.start();
+ }
}
private static void executeFactoryReset(Context context, int level,
@@ -655,18 +667,28 @@
setFactoryResetProperty(true);
long now = System.currentTimeMillis();
setLastFactoryResetTimeMs(now);
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- try {
- RecoverySystem.rebootPromptAndWipeUserData(context, TAG + "," + failedPackage);
- } catch (Throwable t) {
- logRescueException(level, failedPackage, t);
- }
+
+ if (Flags.synchronousRebootInRescueParty()) {
+ try {
+ RecoverySystem.rebootPromptAndWipeUserData(context, TAG + "," + failedPackage);
+ } catch (Throwable t) {
+ logRescueException(level, failedPackage, t);
}
- };
- Thread thread = new Thread(runnable);
- thread.start();
+ } else {
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ RecoverySystem.rebootPromptAndWipeUserData(context,
+ TAG + "," + failedPackage);
+ } catch (Throwable t) {
+ logRescueException(level, failedPackage, t);
+ }
+ }
+ };
+ Thread thread = new Thread(runnable);
+ thread.start();
+ }
}