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
This commit is contained in:
Marco Ballesio
2020-10-21 14:02:05 -07:00
parent ef7605be2e
commit 5ab4fb7529

View File

@@ -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,