diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c6648c5f67901..44fbebade1318 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -16999,6 +16999,15 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void addPendingTopUid(int uid, int pid) { mPendingStartActivityUids.add(uid, pid); + + // If the next top activity is in cached and frozen mode, WM should raise its priority + // to unfreeze it. This is done by calling AMS.updateOomAdj that will lower its oom adj. + // However, WM cannot hold the AMS clock here so the updateOomAdj operation is performed + // in a separate thread asynchronously. Therefore WM can't guarantee AMS will unfreeze + // next top activity on time. This race will fail the following binder transactions WM + // sends to the activity. After this race issue between WM/ATMS and AMS is solved, this + // workaround can be removed. (b/213288355) + mOomAdjuster.mCachedAppOptimizer.unfreezeProcess(pid); } @Override diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java index b18d390476f02..0c3b984aed734 100644 --- a/services/core/java/com/android/server/am/CachedAppOptimizer.java +++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java @@ -183,6 +183,8 @@ public final class CachedAppOptimizer { private final ActivityManagerGlobalLock mProcLock; + private final Object mFreezerLock = new Object(); + private final OnPropertiesChangedListener mOnFlagsChangedListener = new OnPropertiesChangedListener() { @Override @@ -949,8 +951,8 @@ public final class CachedAppOptimizer { } } - @GuardedBy({"mAm", "mProcLock"}) - void unfreezeAppLSP(ProcessRecord app) { + @GuardedBy({"mAm", "mProcLock", "mFreezerLock"}) + void unfreezeAppInternalLSP(ProcessRecord app) { final int pid = app.getPid(); final ProcessCachedOptimizerRecord opt = app.mOptRecord; if (opt.isPendingFreeze()) { @@ -1035,6 +1037,42 @@ public final class CachedAppOptimizer { } } + @GuardedBy({"mAm", "mProcLock"}) + void unfreezeAppLSP(ProcessRecord app) { + synchronized (mFreezerLock) { + unfreezeAppInternalLSP(app); + } + } + + /** + * This quick function works around the race condition between WM/ATMS and AMS, allowing + * the former to directly unfreeze a frozen process before the latter runs updateOomAdj. + * After the race issue is solved, this workaround can be removed. (b/213288355) + * @param pid pid of the process to be unfrozen + */ + @GuardedBy({"mFreezerLock"}) + void unfreezeProcess(int pid) { + synchronized (mFreezerLock) { + ProcessRecord app = mFrozenProcesses.get(pid); + if (app == null) { + return; + } + Slog.i(TAG_AM, "quick sync unfreeze " + pid); + try { + freezeBinder(pid, false); + } catch (RuntimeException e) { + Slog.e(TAG_AM, "Unable to quick unfreeze binder for " + pid); + return; + } + + try { + Process.setProcessFrozen(pid, app.uid, false); + } catch (Exception e) { + Slog.e(TAG_AM, "Unable to quick unfreeze " + pid); + } + } + } + /** * To be called when the given app is killed. */ @@ -1464,8 +1502,6 @@ public final class CachedAppOptimizer { return; } - Slog.d(TAG_AM, "froze " + pid + " " + name); - EventLog.writeEvent(EventLogTags.AM_FREEZE, pid, name); // See above for why we're not taking mPhenotypeFlagLock here