Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8858f6b5 authored by Varun Shah's avatar Varun Shah
Browse files

Rate limit calls to AM.getMemoryInfo().

Apps do not need to call getMemoryInfo any more than 100 times per
second. Rate limit this API - if apps want to consume information about
their own memory usage, they can use the getMyMemoryState API instead.

Flag: android.app.rate_limit_get_memory_info
Bug: 364312431
Test: atest ActivityManagerTest
Test: manually check logs for cache hits/misses
Change-Id: If2494509d76e269b0ad75d8d73bc6848adab490b
parent 5bb80315
Loading
Loading
Loading
Loading
+36 −0
Original line number Original line Diff line number Diff line
@@ -88,6 +88,7 @@ import android.util.Size;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowInsetsController.Appearance;
import android.window.TaskSnapshot;
import android.window.TaskSnapshot;


import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.LocalePicker;
import com.android.internal.app.LocalePicker;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.os.RoSystemProperties;
import com.android.internal.os.RoSystemProperties;
@@ -238,6 +239,14 @@ public class ActivityManager {
    private static final RateLimitingCache<List<ProcessErrorStateInfo>> mErrorProcessesCache =
    private static final RateLimitingCache<List<ProcessErrorStateInfo>> mErrorProcessesCache =
            new RateLimitingCache<>(10, 2);
            new RateLimitingCache<>(10, 2);


    /** Rate-Limiting cache that allows no more than 100 calls to the service per second. */
    @GuardedBy("mMemoryInfoCache")
    private static final RateLimitingCache<MemoryInfo> mMemoryInfoCache =
            new RateLimitingCache<>(10);
    /** Used to store cached results for rate-limited calls to getMemoryInfo(). */
    @GuardedBy("mMemoryInfoCache")
    private static final MemoryInfo mRateLimitedMemInfo = new MemoryInfo();

    /**
    /**
     * Query handler for mGetCurrentUserIdCache - returns a cached value of the current foreground
     * 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.
     * user id if the backstage_power/android.app.cache_get_current_user_id flag is enabled.
@@ -3510,6 +3519,19 @@ public class ActivityManager {
            foregroundAppThreshold = source.readLong();
            foregroundAppThreshold = source.readLong();
        }
        }


        /** @hide */
        public void copyTo(MemoryInfo other) {
            other.advertisedMem = advertisedMem;
            other.availMem = availMem;
            other.totalMem = totalMem;
            other.threshold = threshold;
            other.lowMemory = lowMemory;
            other.hiddenAppThreshold = hiddenAppThreshold;
            other.secondaryServerThreshold = secondaryServerThreshold;
            other.visibleAppThreshold = visibleAppThreshold;
            other.foregroundAppThreshold = foregroundAppThreshold;
        }

        public static final @android.annotation.NonNull Creator<MemoryInfo> CREATOR
        public static final @android.annotation.NonNull Creator<MemoryInfo> CREATOR
                = new Creator<MemoryInfo>() {
                = new Creator<MemoryInfo>() {
            public MemoryInfo createFromParcel(Parcel source) {
            public MemoryInfo createFromParcel(Parcel source) {
@@ -3536,6 +3558,20 @@ public class ActivityManager {
     * manage its memory.
     * manage its memory.
     */
     */
    public void getMemoryInfo(MemoryInfo outInfo) {
    public void getMemoryInfo(MemoryInfo outInfo) {
        if (Flags.rateLimitGetMemoryInfo()) {
            synchronized (mMemoryInfoCache) {
                mMemoryInfoCache.get(() -> {
                    getMemoryInfoInternal(mRateLimitedMemInfo);
                    return mRateLimitedMemInfo;
                });
                mRateLimitedMemInfo.copyTo(outInfo);
            }
        } else {
            getMemoryInfoInternal(outInfo);
        }
    }

    private void getMemoryInfoInternal(MemoryInfo outInfo) {
        try {
        try {
            getService().getMemoryInfo(outInfo);
            getService().getMemoryInfo(outInfo);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
+11 −0
Original line number Original line Diff line number Diff line
@@ -114,3 +114,14 @@ flag {
         purpose: PURPOSE_BUGFIX
         purpose: PURPOSE_BUGFIX
     }
     }
}
}

flag {
     namespace: "backstage_power"
     name: "rate_limit_get_memory_info"
     description: "Rate limit calls to getMemoryInfo using a cache"
     is_fixed_read_only: true
     bug: "364312431"
     metadata {
         purpose: PURPOSE_BUGFIX
     }
}