diff options
author | Sven Gothel <[email protected]> | 2014-01-24 13:05:11 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-01-24 13:05:11 +0100 |
commit | 022c31eefaa0c11fbc069fd35cf5311a556c9ae5 (patch) | |
tree | 15468323ce0ad1d1e368c1aaaba1f594742aacaa /src/java/com/jogamp | |
parent | 2868816971bb80eb226e6edffc527d909ced755b (diff) |
Bug 856 - Android: Support dual ABI (x86 i686 *and* ARMv7arm), i.e. pick 'best' ABI
- Use 'os.arch' as a prelim CPUType for MachineDescription
- Always attempt to load a binary and parse it's elf header
- Linux: self-exe
- Android: gluegen-rt library
- Other: java lib
- Always use details (ABI) if ARM
- Android: Check CPU_TYPE and CPU_TYPE2
// FIXME / HACK:
// We use sCPUType for MachineDescriptionRuntime.getStatic()
// until we have determined the final CPU_TYPE, etc.
// MachineDescriptionRuntime gets notified via MachineDescriptionRuntime.notifyPropsInitialized() below.
//
// We could use Elf Ehdr's machine value to determine the bit-size
// used for it's offset table!
// However, 'os.arch' should be a good guess for this task.
Tested manually on
- Linux x86, x86_64, armhf (raspi)
- Android intel and arm
- Windows x86_64
- OSX x86_64
Diffstat (limited to 'src/java/com/jogamp')
-rw-r--r-- | src/java/com/jogamp/common/os/AndroidVersion.java | 83 | ||||
-rw-r--r-- | src/java/com/jogamp/common/os/Platform.java | 8 |
2 files changed, 84 insertions, 7 deletions
diff --git a/src/java/com/jogamp/common/os/AndroidVersion.java b/src/java/com/jogamp/common/os/AndroidVersion.java index a710310..edf2229 100644 --- a/src/java/com/jogamp/common/os/AndroidVersion.java +++ b/src/java/com/jogamp/common/os/AndroidVersion.java @@ -29,12 +29,25 @@ package com.jogamp.common.os; import java.lang.reflect.Field; +import com.jogamp.common.os.Platform.ABIType; +import com.jogamp.common.os.Platform.CPUFamily; +import com.jogamp.common.os.Platform.CPUType; import com.jogamp.common.util.IntObjectHashMap; import com.jogamp.common.util.ReflectionUtil; public class AndroidVersion { public static final boolean isAvailable; + /** The name of the instruction set (CPU type + ABI convention) of native code. API-4. All lower case.*/ + public static final String CPU_ABI; + public static final CPUType CPU_TYPE; + public static final ABIType ABI_TYPE; + + /** The name of the second instruction set (CPU type + ABI convention) of native code. API-8. All lower case.*/ + public static final String CPU_ABI2; + public static final CPUType CPU_TYPE2; + public static final ABIType ABI_TYPE2; + /** Development codename, or the string "REL" for official release */ public static final String CODENAME; @@ -50,37 +63,90 @@ public class AndroidVersion { /** SDK Version string */ public static final String SDK_NAME; + private static final String androidBuild = "android.os.Build"; private static final String androidBuildVersion = "android.os.Build$VERSION"; private static final String androidBuildVersionCodes = "android.os.Build$VERSION_CODES"; + /** + * Returns {@link CPUType} for matching <code>cpuABI<code>, + * i.e. {@link #CPU_ABI} or {@link #CPU_ABI2}, + * or <code>null</code> for no match. + * <p> + * FIXME: Where is a comprehensive list of known 'android.os.Build.CPU_ABI' and 'android.os.Build.CPU_ABI2' strings ?<br/> + * Fount this one: <code>http://www.kandroid.org/ndk/docs/CPU-ARCH-ABIS.html</code> + * <pre> + * lib/armeabi/libfoo.so + * lib/armeabi-v7a/libfoo.so + * lib/x86/libfoo.so + * lib/mips/libfoo.so + * </pre> + * </p> + */ + private static final CPUType getCPUTypeImpl(String cpuABI) { + if( null == cpuABI ) { + return null; + } else if( cpuABI.equals("armeabi-v7a") ) { + return CPUType.ARMv7; + } else if( cpuABI.equals("armeabi") || + cpuABI.startsWith("arm") ) { // last chance .. + return CPUType.ARM; + } else if( cpuABI.equals("x86") ) { + return CPUType.X86_32; + } else if( cpuABI.equals("mips") ) { // no 32bit vs 64bit identifier ? + return CPUType.MIPS_32; + } else { + return null; + } + } + private static final ABIType getABITypeImpl(final CPUType cpuType, String cpuABI) { + if( null == cpuType || null == cpuABI ) { + return null; + } else if( CPUFamily.ARM != cpuType.family ) { + return ABIType.GENERIC_ABI; + } + return ABIType.EABI_GNU_ARMEL; // FIXME: How will they name ABIType.EABI_GNU_ARMHF + } + static { final ClassLoader cl = AndroidVersion.class.getClassLoader(); + Class<?> abClass = null; + Object abObject= null; Class<?> abvClass = null; Object abvObject= null; Class<?> abvcClass = null; Object abvcObject= null; try { + abClass = ReflectionUtil.getClass(androidBuild, true, cl); + abObject = abClass.newInstance(); abvClass = ReflectionUtil.getClass(androidBuildVersion, true, cl); abvObject = abvClass.newInstance(); abvcClass = ReflectionUtil.getClass(androidBuildVersionCodes, true, cl); abvcObject = abvcClass.newInstance(); } catch (Exception e) { /* n/a */ } - isAvailable = null != abvObject; + isAvailable = null != abObject && null != abvObject && null != abvcObject; if(isAvailable) { - CODENAME = getString(abvClass, abvObject, "CODENAME"); - INCREMENTAL = getString(abvClass, abvObject, "INCREMENTAL"); - RELEASE = getString(abvClass, abvObject, "RELEASE"); + CPU_ABI = getString(abClass, abObject, "CPU_ABI", true); + CPU_ABI2 = getString(abClass, abObject, "CPU_ABI2", true); + CODENAME = getString(abvClass, abvObject, "CODENAME", false); + INCREMENTAL = getString(abvClass, abvObject, "INCREMENTAL", false); + RELEASE = getString(abvClass, abvObject, "RELEASE", false); SDK_INT = getInt(abvClass, abvObject, "SDK_INT"); final IntObjectHashMap version_codes = getVersionCodes(abvcClass, abvcObject); final String sdk_name = (String) version_codes.get(SDK_INT); SDK_NAME = ( null != sdk_name ) ? sdk_name : "SDK_"+SDK_INT ; } else { + CPU_ABI = null; + CPU_ABI2 = null; CODENAME = null; INCREMENTAL = null; RELEASE = null; SDK_INT = -1; SDK_NAME = null; } + CPU_TYPE = getCPUTypeImpl(CPU_ABI); + ABI_TYPE = getABITypeImpl(CPU_TYPE, CPU_ABI); + CPU_TYPE2 = getCPUTypeImpl(CPU_ABI2); + ABI_TYPE2 = getABITypeImpl(CPU_TYPE2, CPU_ABI2); } private static final IntObjectHashMap getVersionCodes(Class<?> cls, Object obj) { @@ -97,10 +163,15 @@ public class AndroidVersion { return map; } - private static final String getString(Class<?> cls, Object obj, String name) { + private static final String getString(Class<?> cls, Object obj, String name, boolean lowerCase) { try { Field f = cls.getField(name); - return (String) f.get(obj); + final String s = (String) f.get(obj); + if( lowerCase && null != s ) { + return s.toLowerCase(); + } else { + return s; + } } catch (Exception e) { e.printStackTrace(); /* n/a */ } return null; } diff --git a/src/java/com/jogamp/common/os/Platform.java b/src/java/com/jogamp/common/os/Platform.java index ee57d6a..e410e81 100644 --- a/src/java/com/jogamp/common/os/Platform.java +++ b/src/java/com/jogamp/common/os/Platform.java @@ -76,6 +76,8 @@ public class Platform extends PlatformPropsImpl { PPC( 0x00020000), /** SPARC */ SPARC( 0x00030000), + /** Mips */ + MIPS( 0x00040000), /** PA RISC */ PA_RISC(0xFFFF0000), /** Itanium */ @@ -107,6 +109,10 @@ public class Platform extends PlatformPropsImpl { SPARC_32( CPUFamily.SPARC, 0x0001), /** SPARC 64bit */ SPARCV9_64(CPUFamily.SPARC, 0x0002), + /** MIPS 32bit */ + MIPS_32( CPUFamily.MIPS, 0x0001), + /** MIPS 64bit */ + MIPS_64( CPUFamily.MIPS, 0x0002), /** Itanium default */ IA64( CPUFamily.IA64, 0x0000), /** PA_RISC2_0 */ @@ -308,7 +314,7 @@ public class Platform extends PlatformPropsImpl { /** * Returns the OS type. - * <p>In case of {@link OSType#ANDROID} the OS name, see {@link #getOSName()}, is Linux</p> + * <p>In case of {@link OSType#ANDROID} the {@link #getOSName() OS name}, is Linux</p> */ public static OSType getOSType() { return OS_TYPE; |