From 9fe53e4d26f007a15057e0cb139dd765efbc8f9c Mon Sep 17 00:00:00 2001 From: Marco Ballesio Date: Wed, 21 Oct 2020 14:02:05 -0700 Subject: CachedAppOptimizer: ensure binder is never frozen with app unfrozen Unfreezing a binder interface after the app, as well as freezing it before the app, opens a time window during wich the process is active and yet synchrnous binder transactions would fail. Unfreeze binder before the app, and similarly freeze it after freezing, to ensure consistent states. Bug: b/171239744 Test: verified correct working of the sequence by manually sending synchronous messages during the critical intervals. Change-Id: I5fad4cdf497a567aceb15b1fc3025b049c54983e --- .../com/android/server/am/CachedAppOptimizer.java | 41 +++++++++++----------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java index 8112bb854b71..cd0d5b47c238 100644 --- a/services/core/java/com/android/server/am/CachedAppOptimizer.java +++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java @@ -776,6 +776,17 @@ public final class CachedAppOptimizer { long freezeTime = app.freezeUnfreezeTime; + try { + freezeBinder(app.pid, false); + } catch (RuntimeException e) { + Slog.e(TAG_AM, "Unable to unfreeze binder for " + app.pid + " " + app.processName + + ". Killing it"); + app.kill("Unable to unfreeze", + ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_INVALID_STATE, true); + return; + } + try { Process.setProcessFrozen(app.pid, app.uid, false); @@ -783,21 +794,10 @@ public final class CachedAppOptimizer { app.frozen = false; } catch (Exception e) { Slog.e(TAG_AM, "Unable to unfreeze " + app.pid + " " + app.processName - + ". Any related user experience might be hanged."); + + ". This might cause inconsistency or UI hangs."); } if (!app.frozen) { - try { - freezeBinder(app.pid, false); - } catch (RuntimeException e) { - Slog.e(TAG_AM, "Unable to unfreeze binder for " + app.pid + " " + app.processName - + ". Killing it"); - app.kill("Unable to unfreeze", - ApplicationExitInfo.REASON_OTHER, - ApplicationExitInfo.SUBREASON_INVALID_STATE, true); - return; - } - if (DEBUG_FREEZER) { Slog.d(TAG_AM, "sync unfroze " + app.pid + " " + app.processName); } @@ -1110,14 +1110,6 @@ public final class CachedAppOptimizer { return; } - try { - freezeBinder(pid, true); - } catch (RuntimeException e) { - // TODO: it might be preferable to kill the target pid in this case - Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name); - return; - } - if (pid == 0 || proc.frozen) { // Already frozen or not a real process, either one being // launched or one being killed @@ -1146,6 +1138,15 @@ public final class CachedAppOptimizer { EventLog.writeEvent(EventLogTags.AM_FREEZE, pid, name); + try { + freezeBinder(pid, true); + } catch (RuntimeException e) { + Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name); + proc.kill("Unable to freeze binder interface", + ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_INVALID_STATE, true); + } + // See above for why we're not taking mPhenotypeFlagLock here if (mRandom.nextFloat() < mFreezerStatsdSampleRate) { FrameworkStatsLog.write(FrameworkStatsLog.APP_FREEZE_CHANGED, -- cgit v1.2.3-59-g8ed1b