diff --git a/core/api/system-current.txt b/core/api/system-current.txt index c723fb757aee3..1e3b362dc8ff0 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -3414,6 +3414,8 @@ package android.content.pm { field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS"; field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio"; field public static final String FEATURE_CONTEXT_HUB = "android.hardware.context_hub"; + field public static final String FEATURE_EROFS = "android.software.erofs"; + field public static final String FEATURE_EROFS_LEGACY = "android.software.erofs_legacy"; field public static final String FEATURE_GAME_SERVICE = "android.software.game_service"; field public static final String FEATURE_INCREMENTAL_DELIVERY = "android.software.incremental_delivery"; field public static final String FEATURE_REBOOT_ESCROW = "android.hardware.reboot_escrow"; diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 81c941eedef0b..c91ee13956877 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -4086,6 +4086,28 @@ public abstract class PackageManager { public static final String FEATURE_INCREMENTAL_DELIVERY = "android.software.incremental_delivery"; + /** + * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device + * has the requisite kernel support for the EROFS filesystem present in 4.19 kernels as a + * staging driver, which lacks 0padding and big pcluster support. + * + * @hide + */ + @SystemApi + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_EROFS_LEGACY = "android.software.erofs_legacy"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device + * has the requisite kernel support for the EROFS filesystem present in 5.10 kernels, which + * has 0padding, big pcluster, and chunked index support. + * + * @hide + */ + @SystemApi + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_EROFS = "android.software.erofs"; + /** * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: * The device has tuner hardware to support tuner operations. diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index e281853d31bf5..db41d333e1d44 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -31,6 +31,7 @@ import android.os.FileUtils; import android.os.Process; import android.os.SystemProperties; import android.os.Trace; +import android.os.VintfRuntimeInfo; import android.os.incremental.IncrementalManager; import android.os.storage.StorageManager; import android.permission.PermissionManager.SplitPermissionInfo; @@ -57,7 +58,10 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -1447,6 +1451,14 @@ public class SystemConfig { addFeature(PackageManager.FEATURE_IPSEC_TUNNELS, 0); } + if (isFilesystemSupported("erofs")) { + if (isKernelVersionAtLeast(5, 10)) { + addFeature(PackageManager.FEATURE_EROFS, 0); + } else if (isKernelVersionAtLeast(4, 19)) { + addFeature(PackageManager.FEATURE_EROFS_LEGACY, 0); + } + } + for (String featureName : mUnavailableFeatures) { removeFeature(featureName); } @@ -1816,4 +1828,29 @@ public class SystemConfig { private static boolean isSystemProcess() { return Process.myUid() == Process.SYSTEM_UID; } + + private static boolean isFilesystemSupported(String fs) { + try { + final byte[] fsTableData = Files.readAllBytes(Paths.get("/proc/filesystems")); + final String fsTable = new String(fsTableData, StandardCharsets.UTF_8); + return fsTable.contains("\t" + fs + "\n"); + } catch (Exception e) { + return false; + } + } + + private static boolean isKernelVersionAtLeast(int major, int minor) { + final String kernelVersion = VintfRuntimeInfo.getKernelVersion(); + final String[] parts = kernelVersion.split("\\."); + if (parts.length < 2) { + return false; + } + try { + final int majorVersion = Integer.parseInt(parts[0]); + final int minorVersion = Integer.parseInt(parts[1]); + return majorVersion > major || (majorVersion == major && minorVersion >= minor); + } catch (NumberFormatException e) { + return false; + } + } }