Bug 1485045 - Make Java parts of GeckoView independent from build ABI r=jchen

This allows us to use the same Java code for any native platform,
enabling a "fat" AAR.

Differential Revision: https://phabricator.services.mozilla.com/D11497

--HG--
extra : moz-landing-system : lando
This commit is contained in:
James Willcox 2018-11-14 17:48:58 +00:00
Родитель b97296cf79
Коммит 2b7367c607
7 изменённых файлов: 92 добавлений и 20 удалений

Просмотреть файл

@ -69,8 +69,6 @@ android {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
buildConfigField 'String', "GRE_MILESTONE", "\"${mozconfig.substs.GRE_MILESTONE}\""
// This should really come from the included binaries, but that's not easy.
buildConfigField 'String', "MOZ_APP_ABI", mozconfig.substs['COMPILE_ENVIRONMENT'] ? "\"${ mozconfig.substs.TARGET_XPCOM_ABI}\"" : '"arm-eabi-gcc3"';
buildConfigField 'String', "MOZ_APP_BASENAME", "\"${mozconfig.substs.MOZ_APP_BASENAME}\"";
// For the benefit of future archaeologists:
@ -92,8 +90,6 @@ android {
buildConfigField 'String', "USER_AGENT_GECKOVIEW_MOBILE", "\"Mozilla/5.0 (Android \" + android.os.Build.VERSION.RELEASE + \"; Mobile; rv: ${mozconfig.substs.MOZ_APP_VERSION}) Gecko/${mozconfig.substs.MOZ_APP_VERSION} GeckoView/${mozconfig.substs.MOZ_APP_VERSION}\"";
buildConfigField 'String', "USER_AGENT_GECKOVIEW_TABLET", "\"Mozilla/5.0 (Android \" + android.os.Build.VERSION.RELEASE + \"; Tablet; rv: ${mozconfig.substs.MOZ_APP_VERSION}) Gecko/${mozconfig.substs.MOZ_APP_VERSION} GeckoView/${mozconfig.substs.MOZ_APP_VERSION}\"";
buildConfigField 'String', "ANDROID_CPU_ARCH", "\"${mozconfig.substs.ANDROID_CPU_ARCH}\"";
buildConfigField 'int', 'MIN_SDK_VERSION', mozconfig.substs.MOZ_ANDROID_MIN_SDK_VERSION;
// Is the underlying compiled C/C++ code compiled with --enable-debug?

Просмотреть файл

@ -84,7 +84,7 @@ class ContentDelegateTest : BaseSessionTest() {
assumeThat(sessionRule.env.isMultiprocess, equalTo(true))
// Cannot test x86 debug builds due to Gecko's "ah_crap_handler"
// that waits for debugger to attach during a SIGSEGV.
assumeThat(sessionRule.env.isDebugBuild && sessionRule.env.cpuArch == "x86",
assumeThat(sessionRule.env.isDebugBuild && sessionRule.env.isX86,
equalTo(false))
mainSession.loadUri(CONTENT_CRASH_URL)
@ -115,7 +115,7 @@ class ContentDelegateTest : BaseSessionTest() {
assumeThat(sessionRule.env.isMultiprocess, equalTo(true))
// Cannot test x86 debug builds due to Gecko's "ah_crap_handler"
// that waits for debugger to attach during a SIGSEGV.
assumeThat(sessionRule.env.isDebugBuild && sessionRule.env.cpuArch == "x86",
assumeThat(sessionRule.env.isDebugBuild && sessionRule.env.isX86,
equalTo(false))
mainSession.delegateUntilTestEnd(object : Callbacks.ContentDelegate {
@ -141,7 +141,7 @@ class ContentDelegateTest : BaseSessionTest() {
assumeThat(sessionRule.env.isMultiprocess, equalTo(true))
// Cannot test x86 debug builds due to Gecko's "ah_crap_handler"
// that waits for debugger to attach during a SIGSEGV.
assumeThat(sessionRule.env.isDebugBuild && sessionRule.env.cpuArch == "x86",
assumeThat(sessionRule.env.isDebugBuild && sessionRule.env.isX86,
equalTo(false))
// XXX we need to make sure all sessions in a given content process receive onCrash().

Просмотреть файл

@ -1661,7 +1661,7 @@ class GeckoSessionTestRuleTest : BaseSessionTest(noErrorCollector = true) {
assumeThat(sessionRule.env.isMultiprocess, equalTo(true))
// Cannot test x86 debug builds due to Gecko's "ah_crap_handler"
// that waits for debugger to attach during a SIGSEGV.
assumeThat(sessionRule.env.isDebugBuild && sessionRule.env.cpuArch == "x86",
assumeThat(sessionRule.env.isDebugBuild && sessionRule.env.isX86,
equalTo(false))
mainSession.loadUri(CONTENT_CRASH_URL)
@ -1678,7 +1678,7 @@ class GeckoSessionTestRuleTest : BaseSessionTest(noErrorCollector = true) {
assumeThat(sessionRule.env.shouldShutdownOnCrash(), equalTo(false))
// Cannot test x86 debug builds due to Gecko's "ah_crap_handler"
// that waits for debugger to attach during a SIGSEGV.
assumeThat(sessionRule.env.isDebugBuild && sessionRule.env.cpuArch == "x86",
assumeThat(sessionRule.env.isDebugBuild && sessionRule.env.isX86,
equalTo(false))
sessionRule.session.loadUri(CONTENT_CRASH_URL)

Просмотреть файл

@ -37,7 +37,7 @@ class CrashTest {
fun getTimeoutMillis(): Long {
val env = Environment()
if ("x86" == env.cpuArch) {
if (env.isX86) {
return if (env.isEmulator)
CrashTest.DEFAULT_X86_EMULATOR_TIMEOUT_MILLIS
else

Просмотреть файл

@ -56,12 +56,19 @@ public class Environment {
return BuildConfig.DEBUG_BUILD;
}
public String getCPUArch() {
return BuildConfig.ANDROID_CPU_ARCH;
public boolean isX86() {
final String abi;
if (Build.VERSION.SDK_INT >= 21) {
abi = Build.SUPPORTED_ABIS[0];
} else {
abi = Build.CPU_ABI;
}
return abi.startsWith("x86");
}
public long getScaledTimeoutMillis() {
if ("x86".equals(getCPUArch())) {
if (isX86()) {
return isEmulator() ? DEFAULT_X86_EMULATOR_TIMEOUT_MILLIS
: DEFAULT_X86_DEVICE_TIMEOUT_MILLIS;
}

Просмотреть файл

@ -8,6 +8,7 @@ package org.mozilla.gecko.mozglue;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.annotation.JNITarget;
import org.mozilla.gecko.annotation.RobocopTarget;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.geckoview.BuildConfig;
import android.content.Context;
@ -314,8 +315,10 @@ public final class GeckoLoader {
message.append(lib);
// These might differ. If so, we know why the library won't load!
message.append(": ABI: " + BuildConfig.MOZ_APP_ABI + ", " + getCPUABI());
HardwareUtils.init(context);
message.append(": ABI: " + HardwareUtils.getLibrariesABI() + ", " + getCPUABI());
message.append(": Data: " + context.getApplicationInfo().dataDir);
try {
final boolean appLibExists = new File("/data/app-lib/" + androidPackageName + "/lib" + lib + ".so").exists();
final boolean dataDataExists = new File("/data/data/" + androidPackageName + "/lib/lib" + lib + ".so").exists();

Просмотреть файл

@ -15,6 +15,11 @@ import android.util.Log;
import org.mozilla.gecko.SysInfo;
import org.mozilla.geckoview.BuildConfig;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public final class HardwareUtils {
private static final String LOGTAG = "GeckoHardwareUtils";
@ -30,13 +35,14 @@ public final class HardwareUtils {
private static volatile boolean sIsSmallTablet;
private static volatile boolean sIsTelevision;
private static volatile File sLibDir;
private static volatile int sMachineType = -1;
private HardwareUtils() {
}
public static void init(Context context) {
if (sInited) {
// This is unavoidable, given that HardwareUtils is called from background services.
Log.d(LOGTAG, "HardwareUtils already inited.");
return;
}
@ -53,6 +59,7 @@ public final class HardwareUtils {
}
}
sLibDir = new File(context.getApplicationInfo().dataDir, "lib");
sInited = true;
}
@ -120,6 +127,63 @@ public final class HardwareUtils {
return getPreferredAbi();
}
private static final int ELF_MACHINE_UNKNOWN = 0;
private static final int ELF_MACHINE_X86 = 0x03;
private static final int ELF_MACHINE_X86_64 = 0x3e;
private static final int ELF_MACHINE_ARM = 0x28;
private static final int ELF_MACHINE_AARCH64 = 0xb7;
private static int readElfMachineType(final File file) {
try (final FileInputStream is = new FileInputStream(file)) {
final byte[] buf = new byte[17];
int count = 0;
while (count != buf.length) {
count += is.read(buf, count, buf.length - count);
}
return buf[16];
} catch (FileNotFoundException e) {
Log.w(LOGTAG, String.format("Failed to open %s", file.getAbsolutePath()));
return ELF_MACHINE_UNKNOWN;
} catch (IOException e) {
Log.w(LOGTAG, "Failed to read library", e);
return ELF_MACHINE_UNKNOWN;
}
}
private static String machineTypeToString(int machineType) {
switch (machineType) {
case ELF_MACHINE_X86:
return "x86";
case ELF_MACHINE_X86_64:
return "x86_64";
case ELF_MACHINE_ARM:
return "arm";
case ELF_MACHINE_AARCH64:
return "aarch64";
case ELF_MACHINE_UNKNOWN:
default:
return "unknown";
}
}
private static void initMachineType() {
if (sMachineType >= 0) {
return;
}
sMachineType = readElfMachineType(new File(sLibDir, System.mapLibraryName("mozglue")));
}
/**
* @return The ABI of the libraries installed for this app.
*/
public static String getLibrariesABI() {
initMachineType();
return machineTypeToString(sMachineType);
}
/**
* @return false if the current system is not supported (e.g. APK/system ABI mismatch).
*/
@ -130,14 +194,16 @@ public final class HardwareUtils {
return false;
}
initMachineType();
// See http://developer.android.com/ndk/guides/abis.html
final boolean isSystemX86 = isX86System();
final boolean isSystemARM = !isSystemX86 && isARMSystem();
final boolean isSystemARM64 = isARM64System();
boolean isAppARM = BuildConfig.ANDROID_CPU_ARCH.startsWith("armeabi-v7a");
boolean isAppARM64 = BuildConfig.ANDROID_CPU_ARCH.startsWith("arm64-v8a");
boolean isAppX86 = BuildConfig.ANDROID_CPU_ARCH.startsWith("x86");
final boolean isAppARM = sMachineType == ELF_MACHINE_ARM;
final boolean isAppARM64 = sMachineType == ELF_MACHINE_AARCH64;
final boolean isAppX86 = sMachineType == ELF_MACHINE_X86;
// Only reject known incompatible ABIs. Better safe than sorry.
if ((isSystemX86 && isAppARM) || (isSystemARM && isAppX86)) {
@ -150,7 +216,7 @@ public final class HardwareUtils {
}
Log.w(LOGTAG, "Unknown app/system ABI combination: " +
BuildConfig.MOZ_APP_ABI + " / " + getRealAbi());
machineTypeToString(sMachineType) + " / " + getRealAbi());
return true;
}
}