diff options
| -rw-r--r-- | core/java/android/app/ActivityManager.java | 41 | ||||
| -rw-r--r-- | core/java/android/app/activity_manager.aconfig | 11 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ProcessList.java | 27 |
3 files changed, 61 insertions, 18 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index b4fb4803a2b9..7273e64846c0 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -247,6 +247,14 @@ public class ActivityManager { @GuardedBy("mMemoryInfoCache") private static final MemoryInfo mRateLimitedMemInfo = new MemoryInfo(); + /** Rate-Limiting cache that allows no more than 200 calls to the service per second. */ + @GuardedBy("mMyMemoryStateCache") + private static final RateLimitingCache<RunningAppProcessInfo> mMyMemoryStateCache = + new RateLimitingCache<>(10, 2); + /** Used to store cached results for rate-limited calls to getMyMemoryState(). */ + @GuardedBy("mMyMemoryStateCache") + private static final RunningAppProcessInfo mRateLimitedMemState = new RunningAppProcessInfo(); + /** * Query handler for mGetCurrentUserIdCache - returns a cached value of the current foreground * user id if the backstage_power/android.app.cache_get_current_user_id flag is enabled. @@ -4223,6 +4231,23 @@ public class ActivityManager { lastActivityTime = source.readLong(); } + /** + * Note: only fields that are updated in ProcessList.fillInProcMemInfoLOSP() are copied. + * @hide + */ + public void copyTo(RunningAppProcessInfo other) { + other.pid = pid; + other.uid = uid; + other.flags = flags; + other.lastTrimLevel = lastTrimLevel; + other.importance = importance; + other.lru = lru; + other.importanceReasonCode = importanceReasonCode; + other.processState = processState; + other.isFocused = isFocused; + other.lastActivityTime = lastActivityTime; + } + public static final @android.annotation.NonNull Creator<RunningAppProcessInfo> CREATOR = new Creator<RunningAppProcessInfo>() { public RunningAppProcessInfo createFromParcel(Parcel source) { @@ -4854,7 +4879,21 @@ public class ActivityManager { * {@link RunningAppProcessInfo#lru}, and * {@link RunningAppProcessInfo#importanceReasonCode}. */ - static public void getMyMemoryState(RunningAppProcessInfo outState) { + public static void getMyMemoryState(RunningAppProcessInfo outState) { + if (Flags.rateLimitGetMyMemoryState()) { + synchronized (mMyMemoryStateCache) { + mMyMemoryStateCache.get(() -> { + getMyMemoryStateInternal(mRateLimitedMemState); + return mRateLimitedMemState; + }); + mRateLimitedMemState.copyTo(outState); + } + } else { + getMyMemoryStateInternal(outState); + } + } + + private static void getMyMemoryStateInternal(RunningAppProcessInfo outState) { try { getService().getMyMemoryState(outState); } catch (RemoteException e) { diff --git a/core/java/android/app/activity_manager.aconfig b/core/java/android/app/activity_manager.aconfig index c0c81df465e2..38bd576d607a 100644 --- a/core/java/android/app/activity_manager.aconfig +++ b/core/java/android/app/activity_manager.aconfig @@ -136,3 +136,14 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + namespace: "backstage_power" + name: "rate_limit_get_my_memory_state" + description: "Rate limit calls to getMyMemoryState using a cache" + is_fixed_read_only: true + bug: "365182205" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 5b4e57350c40..e54e4301a4eb 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -4121,19 +4121,6 @@ public final class ProcessList { return false; } - private static int procStateToImportance(int procState, int memAdj, - ActivityManager.RunningAppProcessInfo currApp, - int clientTargetSdk) { - int imp = ActivityManager.RunningAppProcessInfo.procStateToImportanceForTargetSdk( - procState, clientTargetSdk); - if (imp == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) { - currApp.lru = memAdj; - } else { - currApp.lru = 0; - } - return imp; - } - @GuardedBy(anyOf = {"mService", "mProcLock"}) void fillInProcMemInfoLOSP(ProcessRecord app, ActivityManager.RunningAppProcessInfo outInfo, @@ -4151,14 +4138,20 @@ public final class ProcessList { } outInfo.lastTrimLevel = app.mProfile.getTrimMemoryLevel(); final ProcessStateRecord state = app.mState; - int adj = state.getCurAdj(); - int procState = state.getCurProcState(); - outInfo.importance = procStateToImportance(procState, adj, outInfo, - clientTargetSdk); + final int procState = state.getCurProcState(); + outInfo.importance = ActivityManager.RunningAppProcessInfo + .procStateToImportanceForTargetSdk(procState, clientTargetSdk); + if (outInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) { + outInfo.lru = state.getCurAdj(); + } else { + outInfo.lru = 0; + } outInfo.importanceReasonCode = state.getAdjTypeCode(); outInfo.processState = procState; outInfo.isFocused = (app == mService.getTopApp()); outInfo.lastActivityTime = app.getLastActivityTime(); + // Note: ActivityManager$RunningAppProcessInfo.copyTo() must be updated if what gets + // "filled into" outInfo in this method changes. } @GuardedBy(anyOf = {"mService", "mProcLock"}) |