From c796ed6d6237109c54a1122e3b4e76fadaef63d1 Mon Sep 17 00:00:00 2001 From: Sim Sun Date: Thu, 27 Feb 2020 16:45:42 -0800 Subject: [PATCH] Implement Marshmallow sysdpes getSupportedAbis to avoid read /proc/self/exe error on Android M+ Summary: We can't guarantee we have permission to access `/proc/self/exe`. `Os.readlink("/proc/self/exe").contains("64")` is not a perfect way to check is64bit. On Android M, there's a public API to check 64bit. [Process#is64Bit()](https://developer.android.com/reference/android/os/Process#is64Bit()) Differential Revision: D20130485 fbshipit-source-id: f287285056214831d3777255010932d9c7259595 --- java/com/facebook/soloader/SysUtil.java | 39 +++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/java/com/facebook/soloader/SysUtil.java b/java/com/facebook/soloader/SysUtil.java index a978a76..b6bac07 100644 --- a/java/com/facebook/soloader/SysUtil.java +++ b/java/com/facebook/soloader/SysUtil.java @@ -73,10 +73,12 @@ public static void deleteOrThrow(File file) throws IOException { * @return Ordered array of supported ABIs */ public static String[] getSupportedAbis() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - return new String[] {Build.CPU_ABI, Build.CPU_ABI2}; - } else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return MarshmallowSysdeps.getSupportedAbis(); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return LollipopSysdeps.getSupportedAbis(); + } else { + return new String[] {Build.CPU_ABI, Build.CPU_ABI2}; } } @@ -187,6 +189,37 @@ public static boolean is64Bit() throws ErrnoException { @TargetApi(Build.VERSION_CODES.M) @DoNotOptimize private static final class MarshmallowSysdeps { + @DoNotOptimize + public static String[] getSupportedAbis() { + String[] supportedAbis = Build.SUPPORTED_ABIS; + TreeSet allowedAbis = new TreeSet<>(); + // Some devices report both 64-bit and 32-bit ABIs but *actually* run + // the process in 32-bit mode. + // + // Determine the current process bitness and use that to filter + // out incompatible ABIs from SUPPORTED_ABIS. + if (is64Bit()) { + allowedAbis.add(MinElf.ISA.AARCH64.toString()); + allowedAbis.add(MinElf.ISA.X86_64.toString()); + } else { + allowedAbis.add(MinElf.ISA.ARM.toString()); + allowedAbis.add(MinElf.ISA.X86.toString()); + } + // Filter out the incompatible ABIs from the list of supported ABIs, + // retaining the original order. + ArrayList compatibleSupportedAbis = new ArrayList<>(); + for (String abi : supportedAbis) { + if (allowedAbis.contains(abi)) { + compatibleSupportedAbis.add(abi); + } + } + + String[] finalAbis = new String[compatibleSupportedAbis.size()]; + finalAbis = compatibleSupportedAbis.toArray(finalAbis); + + return finalAbis; + } + @DoNotOptimize public static boolean is64Bit() { return android.os.Process.is64Bit();