Merge changes from topic "ddr_size_api"
* changes: Add new field in MemoryInfo to get advertised memory size. Add method to parse the size in FileUtils
This commit is contained in:
@@ -4415,6 +4415,7 @@ package android.app {
|
|||||||
method public void readFromParcel(android.os.Parcel);
|
method public void readFromParcel(android.os.Parcel);
|
||||||
method public void writeToParcel(android.os.Parcel, int);
|
method public void writeToParcel(android.os.Parcel, int);
|
||||||
field @NonNull public static final android.os.Parcelable.Creator<android.app.ActivityManager.MemoryInfo> CREATOR;
|
field @NonNull public static final android.os.Parcelable.Creator<android.app.ActivityManager.MemoryInfo> CREATOR;
|
||||||
|
field public long advertisedMem;
|
||||||
field public long availMem;
|
field public long availMem;
|
||||||
field public boolean lowMemory;
|
field public boolean lowMemory;
|
||||||
field public long threshold;
|
field public long threshold;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import android.annotation.IntRange;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.annotation.RequiresPermission;
|
import android.annotation.RequiresPermission;
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
import android.annotation.SystemService;
|
import android.annotation.SystemService;
|
||||||
import android.annotation.TestApi;
|
import android.annotation.TestApi;
|
||||||
@@ -2812,6 +2813,15 @@ public class ActivityManager {
|
|||||||
* {@link ActivityManager#getMemoryInfo}.
|
* {@link ActivityManager#getMemoryInfo}.
|
||||||
*/
|
*/
|
||||||
public static class MemoryInfo implements Parcelable {
|
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
|
* The available memory on the system. This number should not
|
||||||
* be considered absolute: due to the nature of the kernel, a significant
|
* be considered absolute: due to the nature of the kernel, a significant
|
||||||
@@ -2861,6 +2871,7 @@ public class ActivityManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeLong(advertisedMem);
|
||||||
dest.writeLong(availMem);
|
dest.writeLong(availMem);
|
||||||
dest.writeLong(totalMem);
|
dest.writeLong(totalMem);
|
||||||
dest.writeLong(threshold);
|
dest.writeLong(threshold);
|
||||||
@@ -2872,6 +2883,7 @@ public class ActivityManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void readFromParcel(Parcel source) {
|
public void readFromParcel(Parcel source) {
|
||||||
|
advertisedMem = source.readLong();
|
||||||
availMem = source.readLong();
|
availMem = source.readLong();
|
||||||
totalMem = source.readLong();
|
totalMem = source.readLong();
|
||||||
threshold = source.readLong();
|
threshold = source.readLong();
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ import android.system.ErrnoException;
|
|||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
import android.system.StructStat;
|
import android.system.StructStat;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.DataUnit;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
@@ -83,6 +84,7 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -1309,6 +1311,85 @@ public final class FileUtils {
|
|||||||
return val * pow;
|
return val * pow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static long toBytes(long value, String unit) {
|
||||||
|
unit = unit.toUpperCase();
|
||||||
|
|
||||||
|
if (List.of("B").contains(unit)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (List.of("K", "KB").contains(unit)) {
|
||||||
|
return DataUnit.KILOBYTES.toBytes(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (List.of("M", "MB").contains(unit)) {
|
||||||
|
return DataUnit.MEGABYTES.toBytes(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (List.of("G", "GB").contains(unit)) {
|
||||||
|
return DataUnit.GIGABYTES.toBytes(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (List.of("KI", "KIB").contains(unit)) {
|
||||||
|
return DataUnit.KIBIBYTES.toBytes(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (List.of("MI", "MIB").contains(unit)) {
|
||||||
|
return DataUnit.MEBIBYTES.toBytes(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (List.of("GI", "GIB").contains(unit)) {
|
||||||
|
return DataUnit.GIBIBYTES.toBytes(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Long.MIN_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param fmtSize The string that contains the size to be parsed. The
|
||||||
|
* expected format is:
|
||||||
|
*
|
||||||
|
* <p>"^((\\s*[-+]?[0-9]+)\\s*(B|K|KB|M|MB|G|GB|Ki|KiB|Mi|MiB|Gi|GiB)\\s*)$"
|
||||||
|
*
|
||||||
|
* <p>For example: 10Kb, 500GiB, 100mb. The unit is not case sensitive.
|
||||||
|
*
|
||||||
|
* @return the size in bytes. If {@code fmtSize} has invalid format, it
|
||||||
|
* returns {@link Long#MIN_VALUE}.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static long parseSize(@Nullable String fmtSize) {
|
||||||
|
if (fmtSize == null || fmtSize.isBlank()) {
|
||||||
|
return Long.MIN_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sign = 1;
|
||||||
|
fmtSize = fmtSize.trim();
|
||||||
|
char first = fmtSize.charAt(0);
|
||||||
|
if (first == '-' || first == '+') {
|
||||||
|
if (first == '-') {
|
||||||
|
sign = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmtSize = fmtSize.replace(first + "", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
// Find the last index of the value in fmtSize.
|
||||||
|
while (index < fmtSize.length() && Character.isDigit(fmtSize.charAt(index))) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if number and units are present.
|
||||||
|
if (index == 0 || index == fmtSize.length()) {
|
||||||
|
return Long.MIN_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
long value = sign * Long.valueOf(fmtSize.substring(0, index));
|
||||||
|
String unit = fmtSize.substring(index).trim();
|
||||||
|
|
||||||
|
return toBytes(value, unit);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the given object quietly, ignoring any checked exceptions. Does
|
* Closes the given object quietly, ignoring any checked exceptions. Does
|
||||||
* nothing if the given object is {@code null}.
|
* nothing if the given object is {@code null}.
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import android.annotation.TestApi;
|
|||||||
import android.annotation.UptimeMillisLong;
|
import android.annotation.UptimeMillisLong;
|
||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
import android.os.Build.VERSION_CODES;
|
import android.os.Build.VERSION_CODES;
|
||||||
|
import android.sysprop.MemoryProperties;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
import android.system.OsConstants;
|
import android.system.OsConstants;
|
||||||
@@ -1336,6 +1337,24 @@ public class Process {
|
|||||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
|
||||||
public static final native void sendSignalQuiet(int pid, int signal);
|
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 */
|
/** @hide */
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public static final native long getFreeMemory();
|
public static final native long getFreeMemory();
|
||||||
|
|||||||
@@ -58,10 +58,10 @@ import android.provider.DocumentsContract.Document;
|
|||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
import libcore.io.Streams;
|
|
||||||
|
|
||||||
import com.google.android.collect.Sets;
|
import com.google.android.collect.Sets;
|
||||||
|
|
||||||
|
import libcore.io.Streams;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -523,6 +523,56 @@ public class FileUtilsTest {
|
|||||||
assertEquals(G64, roundStorageSize(G32 + 1));
|
assertEquals(G64, roundStorageSize(G32 + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseSize() {
|
||||||
|
assertEquals(0L, FileUtils.parseSize("0MB"));
|
||||||
|
assertEquals(1_024L, FileUtils.parseSize("1024b"));
|
||||||
|
assertEquals(-1L, FileUtils.parseSize(" -1 b "));
|
||||||
|
assertEquals(0L, FileUtils.parseSize(" -0 gib "));
|
||||||
|
assertEquals(1_000L, FileUtils.parseSize("1K"));
|
||||||
|
assertEquals(1_000L, FileUtils.parseSize("1KB"));
|
||||||
|
assertEquals(10_000L, FileUtils.parseSize("10KB"));
|
||||||
|
assertEquals(100_000L, FileUtils.parseSize("100KB"));
|
||||||
|
assertEquals(1_000_000L, FileUtils.parseSize("1000KB"));
|
||||||
|
assertEquals(1_024_000L, FileUtils.parseSize("1000KiB"));
|
||||||
|
assertEquals(70_000_000L, FileUtils.parseSize("070M"));
|
||||||
|
assertEquals(70_000_000L, FileUtils.parseSize("070MB"));
|
||||||
|
assertEquals(73_400_320L, FileUtils.parseSize("70MiB"));
|
||||||
|
assertEquals(700_000_000L, FileUtils.parseSize("700000KB"));
|
||||||
|
assertEquals(200_000_000L, FileUtils.parseSize("+200MB"));
|
||||||
|
assertEquals(1_000_000_000L, FileUtils.parseSize("1000MB"));
|
||||||
|
assertEquals(1_000_000_000L, FileUtils.parseSize("+1000 mb"));
|
||||||
|
assertEquals(644_245_094_400L, FileUtils.parseSize("600GiB"));
|
||||||
|
assertEquals(999_000_000_000L, FileUtils.parseSize("999GB"));
|
||||||
|
assertEquals(999_000_000_000L, FileUtils.parseSize("999 gB"));
|
||||||
|
assertEquals(9_999_000_000_000L, FileUtils.parseSize("9999GB"));
|
||||||
|
assertEquals(9_000_000_000_000L, FileUtils.parseSize(" 9000 GB "));
|
||||||
|
assertEquals(1_234_000_000_000L, FileUtils.parseSize(" 1234 GB "));
|
||||||
|
assertEquals(1_234_567_890_000L, FileUtils.parseSize(" 1234567890 KB "));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseSize_invalidArguments() {
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize(null));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("null"));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize(""));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize(" "));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("KB"));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("123 dd"));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("Invalid"));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize(" ABC890 KB "));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("-=+90 KB "));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("123"));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("--123"));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("-KB"));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("++123"));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("+"));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("+ 1 +"));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("+--+ 1 +"));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize("1GB+"));
|
||||||
|
assertEquals(Long.MIN_VALUE, FileUtils.parseSize(" + 1234567890 KB "));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTranslateMode() throws Exception {
|
public void testTranslateMode() throws Exception {
|
||||||
assertTranslate("r", O_RDONLY, MODE_READ_ONLY);
|
assertTranslate("r", O_RDONLY, MODE_READ_ONLY);
|
||||||
|
|||||||
@@ -72,4 +72,7 @@ public class ProcessTest extends TestCase {
|
|||||||
assertEquals(-1, Process.getThreadGroupLeader(BAD_PID));
|
assertEquals(-1, Process.getThreadGroupLeader(BAD_PID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testGetAdvertisedMem() {
|
||||||
|
assertTrue(Process.getTotalMemory() <= Process.getAdvertisedMem());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
|
|||||||
import static android.os.Process.SYSTEM_UID;
|
import static android.os.Process.SYSTEM_UID;
|
||||||
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
|
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
|
||||||
import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY;
|
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.getFreeMemory;
|
||||||
import static android.os.Process.getTotalMemory;
|
import static android.os.Process.getTotalMemory;
|
||||||
import static android.os.Process.killProcessQuiet;
|
import static android.os.Process.killProcessQuiet;
|
||||||
@@ -1524,6 +1525,7 @@ public final class ProcessList {
|
|||||||
void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
|
void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
|
||||||
final long homeAppMem = getMemLevel(HOME_APP_ADJ);
|
final long homeAppMem = getMemLevel(HOME_APP_ADJ);
|
||||||
final long cachedAppMem = getMemLevel(CACHED_APP_MIN_ADJ);
|
final long cachedAppMem = getMemLevel(CACHED_APP_MIN_ADJ);
|
||||||
|
outInfo.advertisedMem = getAdvertisedMem();
|
||||||
outInfo.availMem = getFreeMemory();
|
outInfo.availMem = getFreeMemory();
|
||||||
outInfo.totalMem = getTotalMemory();
|
outInfo.totalMem = getTotalMemory();
|
||||||
outInfo.threshold = homeAppMem;
|
outInfo.threshold = homeAppMem;
|
||||||
|
|||||||
Reference in New Issue
Block a user