diff --git a/core/api/current.txt b/core/api/current.txt index 3c5713eba6609..9a76523d94e0d 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -4426,6 +4426,7 @@ package android.app { method public void readFromParcel(android.os.Parcel); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public long advertisedMem; field public long availMem; field public boolean lowMemory; field public long threshold; diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 8ae16df64ace3..da2a76a7b3196 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -29,6 +29,7 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; @@ -2811,6 +2812,15 @@ public class ActivityManager { * {@link ActivityManager#getMemoryInfo}. */ public static class MemoryInfo implements Parcelable { + /** + * The advertised memory of the system, as the end user would encounter in a retail display + * environment. This value might be different from {@code totalMem}. This could be due to + * many reasons. For example, the ODM could reserve part of the memory for the Trusted + * Execution Environment (TEE) which the kernel doesn't have access or knowledge about it. + */ + @SuppressLint("MutableBareField") + public long advertisedMem; + /** * The available memory on the system. This number should not * be considered absolute: due to the nature of the kernel, a significant @@ -2860,6 +2870,7 @@ public class ActivityManager { } public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(advertisedMem); dest.writeLong(availMem); dest.writeLong(totalMem); dest.writeLong(threshold); @@ -2871,6 +2882,7 @@ public class ActivityManager { } public void readFromParcel(Parcel source) { + advertisedMem = source.readLong(); availMem = source.readLong(); totalMem = source.readLong(); threshold = source.readLong(); diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 14082f3388a03..c943a3d1861cc 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -26,6 +26,7 @@ import android.annotation.TestApi; import android.annotation.UptimeMillisLong; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build.VERSION_CODES; +import android.sysprop.MemoryProperties; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; @@ -1330,6 +1331,24 @@ public class Process { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public static final native void sendSignalQuiet(int pid, int signal); + /** + * @return The advertised memory of the system, as the end user would encounter in a retail + * display environment. If the advertised memory is not defined, it returns + * {@code getTotalMemory()} rounded. + * + * @hide + */ + public static final long getAdvertisedMem() { + String formatSize = MemoryProperties.memory_ddr_size().orElse("0KB"); + long memSize = FileUtils.parseSize(formatSize); + + if (memSize == Long.MIN_VALUE) { + return FileUtils.roundStorageSize(getTotalMemory()); + } + + return memSize; + } + /** @hide */ @UnsupportedAppUsage public static final native long getFreeMemory(); diff --git a/core/tests/coretests/src/android/os/ProcessTest.java b/core/tests/coretests/src/android/os/ProcessTest.java index ae4edb97aab00..52846dfbb14b8 100644 --- a/core/tests/coretests/src/android/os/ProcessTest.java +++ b/core/tests/coretests/src/android/os/ProcessTest.java @@ -72,4 +72,7 @@ public class ProcessTest extends TestCase { assertEquals(-1, Process.getThreadGroupLeader(BAD_PID)); } + public void testGetAdvertisedMem() { + assertTrue(Process.getTotalMemory() <= Process.getAdvertisedMem()); + } } diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 992d41637f3f0..d7b38482a4edc 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -27,6 +27,7 @@ import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; import static android.os.Process.SYSTEM_UID; import static android.os.Process.THREAD_PRIORITY_BACKGROUND; import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY; +import static android.os.Process.getAdvertisedMem; import static android.os.Process.getFreeMemory; import static android.os.Process.getTotalMemory; import static android.os.Process.killProcessQuiet; @@ -1532,6 +1533,7 @@ public final class ProcessList { void getMemoryInfo(ActivityManager.MemoryInfo outInfo) { final long homeAppMem = getMemLevel(HOME_APP_ADJ); final long cachedAppMem = getMemLevel(CACHED_APP_MIN_ADJ); + outInfo.advertisedMem = getAdvertisedMem(); outInfo.availMem = getFreeMemory(); outInfo.totalMem = getTotalMemory(); outInfo.threshold = homeAppMem;