Bug 1116589 - Use templated JNI classes in generated bindings; r=snorp

This commit is contained in:
Jim Chen 2015-01-09 19:33:57 -05:00
parent b7e5322f21
commit c02561a822
59 changed files with 4728 additions and 4688 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1056337 - Change default compiler for B2G ICS builds.
Bug 1116589 - Clobber needed to update autogenerated Android library bindings.

View File

@ -22,7 +22,7 @@ public class AnnotationInfo {
narrowChars = aNarrowChars;
catchException = aCatchException;
if (!noThrow && catchException) {
if (noThrow && catchException) {
// It doesn't make sense to have these together
throw new IllegalArgumentException("noThrow and catchException are not allowed together");
}

View File

@ -20,9 +20,11 @@ public class AnnotationProcessor {
public static final String GENERATED_COMMENT =
"// GENERATED CODE\n" +
"// Generated by the Java program at /build/annotationProcessors at compile time from\n" +
"// annotations on Java methods. To update, change the annotations on the corresponding Java\n" +
"// methods and rerun the build. Manually updating this file will cause your build to fail.\n\n";
"// Generated by the Java program at /build/annotationProcessors at compile time\n" +
"// from annotations on Java methods. To update, change the annotations on the\n" +
"// corresponding Javamethods and rerun the build. Manually updating this file\n" +
"// will cause your build to fail.\n" +
"\n";
public static void main(String[] args) {
// We expect a list of jars on the commandline. If missing, whinge about it.
@ -44,29 +46,24 @@ public class AnnotationProcessor {
Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args);
StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
headerFile.append("#ifndef GeneratedJNIWrappers_h__\n" +
"#define GeneratedJNIWrappers_h__\n\n" +
"#include \"nsXPCOMStrings.h\"\n" +
"#include \"AndroidJavaWrappers.h\"\n" +
"\n" +
"namespace mozilla {\n" +
"namespace widget {\n" +
"namespace android {\n" +
"void InitStubs(JNIEnv *env);\n\n");
headerFile.append(
"#ifndef GeneratedJNIWrappers_h__\n" +
"#define GeneratedJNIWrappers_h__\n" +
"\n" +
"#include \"mozilla/jni/Refs.h\"\n" +
"\n" +
"namespace mozilla {\n" +
"namespace widget {\n" +
"\n");
StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
implementationFile.append("#include \"GeneratedJNIWrappers.h\"\n" +
"#include \"AndroidBridgeUtilities.h\"\n" +
"#include \"nsXPCOMStrings.h\"\n" +
"#include \"AndroidBridge.h\"\n" +
"\n" +
"namespace mozilla {\n" +
"namespace widget {\n" +
"namespace android {\n");
// Used to track the calls to the various class-specific initialisation functions.
StringBuilder stubInitialiser = new StringBuilder();
stubInitialiser.append("void InitStubs(JNIEnv *env) {\n");
implementationFile.append(
"#include \"GeneratedJNIWrappers.h\"\n" +
"#include \"mozilla/jni/Accessors.h\"\n" +
"\n" +
"namespace mozilla {\n" +
"namespace widget {\n" +
"\n");
while (jarClassIterator.hasNext()) {
ClassWithOptions aClassTuple = jarClassIterator.next();
@ -79,9 +76,7 @@ public class AnnotationProcessor {
if (!methodIterator.hasNext()) {
continue;
}
generatorInstance = new CodeGenerator(aClassTuple.wrappedClass, aClassTuple.generatedName);
stubInitialiser.append(" ").append(aClassTuple.generatedName).append("::InitStubs(env);\n");
generatorInstance = new CodeGenerator(aClassTuple);
// Iterate all annotated members in this class..
while (methodIterator.hasNext()) {
@ -103,18 +98,16 @@ public class AnnotationProcessor {
implementationFile.append(generatorInstance.getWrapperFileContents());
}
implementationFile.append('\n');
stubInitialiser.append("}");
implementationFile.append(stubInitialiser);
implementationFile.append(
"\n" +
"} /* widget */\n" +
"} /* mozilla */\n");
implementationFile.append("\n} /* android */\n" +
"} /* widget */\n" +
"} /* mozilla */\n");
headerFile.append("\n} /* android */\n" +
"} /* widget */\n" +
"} /* mozilla */\n" +
"#endif\n");
headerFile.append(
"\n" +
"} /* widget */\n" +
"} /* mozilla */\n" +
"#endif // GeneratedJNIWrappers_h__\n");
writeOutputFiles(headerFile, implementationFile);
long e = System.currentTimeMillis();
@ -158,4 +151,4 @@ public class AnnotationProcessor {
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -36,9 +36,11 @@ import java.lang.reflect.Modifier;
public class SDKProcessor {
public static final String GENERATED_COMMENT =
"// GENERATED CODE\n" +
"// Generated by the Java program at /build/annotationProcessors at compile time from\n" +
"// annotations on Java methods. To update, change the annotations on the corresponding Java\n" +
"// methods and rerun the build. Manually updating this file will cause your build to fail.\n\n";
"// Generated by the Java program at /build/annotationProcessors at compile time\n" +
"// from annotations on Java methods. To update, change the annotations on the\n" +
"// corresponding Javamethods and rerun the build. Manually updating this file\n" +
"// will cause your build to fail.\n" +
"\n";
private static ApiLookup sApiLookup;
private static int sMaxSdkVersion;
@ -68,38 +70,34 @@ public class SDKProcessor {
// Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args);
StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
headerFile.append("#ifndef " + generatedFilePrefix + "_h__\n" +
"#define " + generatedFilePrefix + "_h__\n" +
"#include \"nsXPCOMStrings.h\"\n" +
"#include \"AndroidJavaWrappers.h\"\n" +
"\n" +
"namespace mozilla {\n" +
"namespace widget {\n" +
"namespace android {\n" +
"namespace sdk {\n" +
"void Init" + generatedFilePrefix + "Stubs(JNIEnv *jEnv);\n\n");
headerFile.append(
"#ifndef " + generatedFilePrefix + "_h__\n" +
"#define " + generatedFilePrefix + "_h__\n" +
"\n" +
"#include \"mozilla/jni/Refs.h\"\n" +
"\n" +
"namespace mozilla {\n" +
"namespace widget {\n" +
"namespace sdk {\n" +
"\n");
StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
implementationFile.append("#include \"" + generatedFilePrefix + ".h\"\n" +
"#include \"AndroidBridgeUtilities.h\"\n" +
"#include \"nsXPCOMStrings.h\"\n" +
"#include \"AndroidBridge.h\"\n" +
"\n" +
"namespace mozilla {\n" +
"namespace widget {\n" +
"namespace android {\n" +
"namespace sdk {\n");
implementationFile.append(
"#include \"" + generatedFilePrefix + ".h\"\n" +
"#include \"mozilla/jni/Accessors.h\"\n" +
"\n" +
"namespace mozilla {\n" +
"namespace widget {\n" +
"namespace sdk {\n" +
"\n");
// Used to track the calls to the various class-specific initialisation functions.
StringBuilder stubInitializer = new StringBuilder();
stubInitializer.append("void Init" + generatedFilePrefix + "Stubs(JNIEnv *jEnv) {\n");
ClassLoader loader = null;
try {
loader = URLClassLoader.newInstance(new URL[] { new URL("file://" + sdkJar) },
SDKProcessor.class.getClassLoader());
} catch (Exception e) {
System.out.println(e);
throw new RuntimeException(e.toString());
}
for (Iterator<String> i = classes.iterator(); i.hasNext(); ) {
@ -107,25 +105,20 @@ public class SDKProcessor {
System.out.println("Looking up: " + className);
generateClass(Class.forName(className, true, loader),
stubInitializer,
implementationFile,
headerFile);
}
implementationFile.append('\n');
stubInitializer.append("}");
implementationFile.append(stubInitializer);
implementationFile.append(
"} /* sdk */\n" +
"} /* widget */\n" +
"} /* mozilla */\n");
implementationFile.append("\n} /* sdk */\n" +
"} /* android */\n" +
"} /* widget */\n" +
"} /* mozilla */\n");
headerFile.append("\n} /* sdk */\n" +
"} /* android */\n" +
"} /* widget */\n" +
"} /* mozilla */\n" +
"#endif\n");
headerFile.append(
"} /* sdk */\n" +
"} /* widget */\n" +
"} /* mozilla */\n" +
"#endif\n");
writeOutputFiles(outdir, generatedFilePrefix, headerFile, implementationFile);
long e = System.currentTimeMillis();
@ -145,12 +138,13 @@ public class SDKProcessor {
int version = 0;
if (m instanceof Method || m instanceof Constructor) {
version = sApiLookup.getCallVersion(Utils.getTypeSignatureStringForClass(m.getDeclaringClass()),
m.getName(),
Utils.getTypeSignatureStringForMember(m));
version = sApiLookup.getCallVersion(
Utils.getClassDescriptor(m.getDeclaringClass()),
m.getName(),
Utils.getSignature(m));
} else if (m instanceof Field) {
version = sApiLookup.getFieldVersion(Utils.getTypeSignatureStringForClass(m.getDeclaringClass()),
m.getName());
version = sApiLookup.getFieldVersion(
Utils.getClassDescriptor(m.getDeclaringClass()), m.getName());
} else {
throw new IllegalArgumentException("expected member to be Method, Constructor, or Field");
}
@ -168,13 +162,11 @@ public class SDKProcessor {
}
private static void generateClass(Class<?> clazz,
StringBuilder stubInitializer,
StringBuilder implementationFile,
StringBuilder headerFile) {
String generatedName = clazz.getSimpleName();
CodeGenerator generator = new CodeGenerator(clazz, generatedName, true);
stubInitializer.append(" ").append(generatedName).append("::InitStubs(jEnv);\n");
CodeGenerator generator = new CodeGenerator(new ClassWithOptions(clazz, generatedName));
generator.generateMembers(sortAndFilterMembers(clazz.getDeclaredConstructors()));
generator.generateMembers(sortAndFilterMembers(clazz.getDeclaredMethods()));

View File

@ -57,16 +57,16 @@ public class AlphabeticAnnotatableEntityComparator<T extends Member> implements
}
// The names were the same, so we need to compare signatures to find their uniqueness..
lName = Utils.getTypeSignatureStringForMethod(aLhs);
rName = Utils.getTypeSignatureStringForMethod(aRhs);
lName = Utils.getSignature(aLhs);
rName = Utils.getSignature(aRhs);
return lName.compareTo(rName);
}
private static int compare(Constructor<?> aLhs, Constructor<?> aRhs) {
// The names will be the same, so we need to compare signatures to find their uniqueness..
String lName = Utils.getTypeSignatureString(aLhs);
String rName = Utils.getTypeSignatureString(aRhs);
String lName = Utils.getSignature(aLhs);
String rName = Utils.getSignature(aRhs);
return lName.compareTo(rName);
}

View File

@ -119,8 +119,7 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
// If the method name was not explicitly given in the annotation generate one...
if (stubName.isEmpty()) {
String aMethodName = candidateElement.getName();
stubName = aMethodName.substring(0, 1).toUpperCase() + aMethodName.substring(1);
stubName = Utils.getNativeName(candidateElement);
}
AnnotationInfo annotationInfo = new AnnotationInfo(
@ -130,11 +129,15 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
}
}
// If no annotation found, we might be expected to generate anyway using default arguments,
// thanks to the "Generate everything" annotation.
// If no annotation found, we might be expected to generate anyway
// using default arguments, thanks to the "Generate everything" annotation.
if (mIterateEveryEntry) {
AnnotationInfo annotationInfo = new AnnotationInfo(
candidateElement.getName(), false, false, false, false);
Utils.getNativeName(candidateElement),
/* multithreaded */ true,
/* noThrow */ false,
/* narrowChars */ false,
/* catchException */ false);
mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
return;
}

View File

@ -4,7 +4,8 @@
package org.mozilla.gecko.annotationProcessors.utils;
import java.lang.annotation.Annotation;
import org.mozilla.gecko.annotationProcessors.AnnotationInfo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
@ -18,647 +19,229 @@ import java.util.HashMap;
public class Utils {
// A collection of lookup tables to simplify the functions to follow...
private static final HashMap<String, String> sBasicCTypes = new HashMap<String, String>();
private static final HashMap<String, String> NATIVE_TYPES = new HashMap<String, String>();
static {
sBasicCTypes.put("void", "void");
sBasicCTypes.put("int", "int32_t");
sBasicCTypes.put("boolean", "bool");
sBasicCTypes.put("long", "int64_t");
sBasicCTypes.put("double", "jdouble");
sBasicCTypes.put("float", "jfloat");
sBasicCTypes.put("char", "uint16_t");
sBasicCTypes.put("byte", "int8_t");
sBasicCTypes.put("short", "int16_t");
NATIVE_TYPES.put("void", "void");
NATIVE_TYPES.put("boolean", "bool");
NATIVE_TYPES.put("byte", "int8_t");
NATIVE_TYPES.put("char", "char16_t");
NATIVE_TYPES.put("short", "int16_t");
NATIVE_TYPES.put("int", "int32_t");
NATIVE_TYPES.put("long", "int64_t");
NATIVE_TYPES.put("float", "float");
NATIVE_TYPES.put("double", "double");
}
private static final HashMap<String, String> sArrayCTypes = new HashMap<String, String>();
private static final HashMap<String, String> NATIVE_ARRAY_TYPES = new HashMap<String, String>();
static {
sArrayCTypes.put("int", "jintArray");
sArrayCTypes.put("boolean", "jbooleanArray");
sArrayCTypes.put("long", "jlongArray");
sArrayCTypes.put("double", "jdoubleArray");
sArrayCTypes.put("float", "jfloatArray");
sArrayCTypes.put("char", "jcharArray");
sArrayCTypes.put("byte", "jbyteArray");
sArrayCTypes.put("short", "jshortArray");
NATIVE_ARRAY_TYPES.put("boolean", "mozilla::jni::BooleanArray");
NATIVE_ARRAY_TYPES.put("byte", "mozilla::jni::ByteArray");
NATIVE_ARRAY_TYPES.put("char", "mozilla::jni::CharArray");
NATIVE_ARRAY_TYPES.put("short", "mozilla::jni::ShortArray");
NATIVE_ARRAY_TYPES.put("int", "mozilla::jni::IntArray");
NATIVE_ARRAY_TYPES.put("long", "mozilla::jni::LongArray");
NATIVE_ARRAY_TYPES.put("float", "mozilla::jni::FloatArray");
NATIVE_ARRAY_TYPES.put("double", "mozilla::jni::DoubleArray");
}
private static final HashMap<String, String> sStaticCallTypes = new HashMap<String, String>();
private static final HashMap<String, String> CLASS_DESCRIPTORS = new HashMap<String, String>();
static {
sStaticCallTypes.put("void", "CallStaticVoidMethod");
sStaticCallTypes.put("int", "CallStaticIntMethod");
sStaticCallTypes.put("boolean", "CallStaticBooleanMethod");
sStaticCallTypes.put("long", "CallStaticLongMethod");
sStaticCallTypes.put("double", "CallStaticDoubleMethod");
sStaticCallTypes.put("float", "CallStaticFloatMethod");
sStaticCallTypes.put("char", "CallStaticCharMethod");
sStaticCallTypes.put("byte", "CallStaticByteMethod");
sStaticCallTypes.put("short", "CallStaticShortMethod");
}
private static final HashMap<String, String> sInstanceCallTypes = new HashMap<String, String>();
static {
sInstanceCallTypes.put("void", "CallVoidMethod");
sInstanceCallTypes.put("int", "CallIntMethod");
sInstanceCallTypes.put("boolean", "CallBooleanMethod");
sInstanceCallTypes.put("long", "CallLongMethod");
sInstanceCallTypes.put("double", "CallDoubleMethod");
sInstanceCallTypes.put("float", "CallFloatMethod");
sInstanceCallTypes.put("char", "CallCharMethod");
sInstanceCallTypes.put("byte", "CallByteMethod");
sInstanceCallTypes.put("short", "CallShortMethod");
}
private static final HashMap<String, String> sFieldTypes = new HashMap<String, String>();
static {
sFieldTypes.put("int", "Int");
sFieldTypes.put("boolean", "Boolean");
sFieldTypes.put("long", "Long");
sFieldTypes.put("double", "Double");
sFieldTypes.put("float", "Float");
sFieldTypes.put("char", "Char");
sFieldTypes.put("byte", "Byte");
sFieldTypes.put("short", "Short");
}
private static final HashMap<String, String> sFailureReturns = new HashMap<String, String>();
static {
sFailureReturns.put("java.lang.Void", "");
sFailureReturns.put("void", "");
sFailureReturns.put("int", " 0");
sFailureReturns.put("boolean", " false");
sFailureReturns.put("long", " 0");
sFailureReturns.put("double", " 0.0");
sFailureReturns.put("float", " 0.0");
sFailureReturns.put("char", " 0");
sFailureReturns.put("byte", " 0");
sFailureReturns.put("short", " 0");
}
private static final HashMap<String, String> sCanonicalSignatureParts = new HashMap<String, String>();
static {
sCanonicalSignatureParts.put("java/lang/Void", "V");
sCanonicalSignatureParts.put("void", "V");
sCanonicalSignatureParts.put("int", "I");
sCanonicalSignatureParts.put("boolean", "Z");
sCanonicalSignatureParts.put("long", "J");
sCanonicalSignatureParts.put("double", "D");
sCanonicalSignatureParts.put("float", "F");
sCanonicalSignatureParts.put("char", "C");
sCanonicalSignatureParts.put("byte", "B");
sCanonicalSignatureParts.put("short", "S");
}
private static final HashMap<String, String> sDefaultParameterValues = new HashMap<String, String>();
static {
sDefaultParameterValues.put("int", "0");
sDefaultParameterValues.put("boolean", "false");
sDefaultParameterValues.put("long", "0");
sDefaultParameterValues.put("double", "0");
sDefaultParameterValues.put("float", "0.0");
sDefaultParameterValues.put("char", "0");
sDefaultParameterValues.put("byte", "0");
sDefaultParameterValues.put("short", "0");
CLASS_DESCRIPTORS.put("void", "V");
CLASS_DESCRIPTORS.put("boolean", "Z");
CLASS_DESCRIPTORS.put("byte", "B");
CLASS_DESCRIPTORS.put("char", "C");
CLASS_DESCRIPTORS.put("short", "S");
CLASS_DESCRIPTORS.put("int", "I");
CLASS_DESCRIPTORS.put("long", "J");
CLASS_DESCRIPTORS.put("float", "F");
CLASS_DESCRIPTORS.put("double", "D");
}
/**
* Get the C type corresponding to the provided type parameter. Used for generating argument
* types for the wrapper method.
* Get the C++ type corresponding to the provided type parameter.
*
* @param type Class to determine the corresponding JNI type for.
* @return true if the type an object type, false otherwise.
* @return C++ type as a String
*/
public static String getCParameterType(Class<?> type, boolean aNarrowChars) {
String name = type.getCanonicalName();
if (sBasicCTypes.containsKey(name)) {
return sBasicCTypes.get(name);
}
// Are we dealing with an array type?
int len = name.length();
if (name.endsWith("[]")) {
// Determine if it is a 2D array - these map to jobjectArrays
name = name.substring(0, len - 2);
if (name.endsWith("[]")) {
return "jobjectArray";
} else {
// Which flavour of Array is it?
if (sArrayCTypes.containsKey(name)) {
return sArrayCTypes.get(name);
}
return "jobjectArray";
}
}
// Not an array type, check the remaining possibilities before we fall back to jobject
public static String getNativeParameterType(Class<?> type, AnnotationInfo info) {
final String name = type.getName().replace('.', '/');
// Check for CharSequences (Strings and things that are string-like)
if (isCharSequence(type)) {
if (aNarrowChars) {
return "const nsACString&";
}
return "const nsAString&";
if (NATIVE_TYPES.containsKey(name)) {
return NATIVE_TYPES.get(name);
}
if (name.equals("java.lang.Class")) {
if (type.isArray()) {
final String compName = type.getComponentType().getName();
if (NATIVE_ARRAY_TYPES.containsKey(compName)) {
return NATIVE_ARRAY_TYPES.get(compName) + "::Param";
}
return "mozilla::jni::ObjectArray::Param";
}
if (type == String.class || type == CharSequence.class) {
return "mozilla::jni::String::Param";
}
if (type == Class.class) {
// You're doing reflection on Java objects from inside C, returning Class objects
// to C, generating the corresponding code using this Java program. Really?!
return "jclass";
return "mozilla::jni::ClassObject::Param";
}
if (name.equals("java.lang.Throwable")) {
return "jthrowable";
if (type == Throwable.class) {
return "mozilla::jni::Throwable::Param";
}
return "jobject";
return "mozilla::jni::Object::Param";
}
/**
* For a given Java type, get the corresponding C++ type if we're returning it from a function.
*
* @param type The Java return type.
* @return A string representation of the C++ return type.
*/
public static String getCReturnType(Class<?> type, boolean aNarrowChars) {
if (type.getCanonicalName().equals("java.lang.Void")) {
return "void";
}
String cParameterType = getCParameterType(type, aNarrowChars);
if (cParameterType.equals("const nsAString&") || cParameterType.equals("const nsACString&")) {
return "jstring";
} else {
return cParameterType;
}
}
public static String getNativeReturnType(Class<?> type, AnnotationInfo info) {
final String name = type.getName().replace('.', '/');
/**
* Gets the type-specific part of the JNI function to use to get or set a field of a given type.
*
* @param aFieldType The Java type of the field.
* @return A string representation of the JNI call function substring to use.
*/
public static String getFieldType(Class<?> aFieldType) {
String name = aFieldType.getCanonicalName();
if (sFieldTypes.containsKey(name)) {
return sFieldTypes.get(name);
if (NATIVE_TYPES.containsKey(name)) {
return NATIVE_TYPES.get(name);
}
return "Object";
}
/**
* Gets the appropriate JNI call function to use to invoke a Java method with the given return
* type. This, plus a call postfix (Such as "A") forms a complete JNI call function name.
*
* @param aReturnType The Java return type of the method being generated.
* @param isStatic Boolean indicating if the underlying Java method is declared static.
* @return A string representation of the JNI call function prefix to use.
*/
public static String getCallPrefix(Class<?> aReturnType, boolean isStatic) {
String name = aReturnType.getCanonicalName();
if (isStatic) {
if (sStaticCallTypes.containsKey(name)) {
return sStaticCallTypes.get(name);
if (type.isArray()) {
final String compName = type.getComponentType().getName();
if (NATIVE_ARRAY_TYPES.containsKey(compName)) {
return NATIVE_ARRAY_TYPES.get(compName) + "::LocalRef";
}
return "CallStaticObjectMethod";
} else {
if (sInstanceCallTypes.containsKey(name)) {
return sInstanceCallTypes.get(name);
}
return "CallObjectMethod";
return "mozilla::jni::ObjectArray::LocalRef";
}
if (type == String.class) {
return "mozilla::jni::String::LocalRef";
}
if (type == Class.class) {
// You're doing reflection on Java objects from inside C, returning Class objects
// to C, generating the corresponding code using this Java program. Really?!
return "mozilla::jni::ClassObject::LocalRef";
}
if (type == Throwable.class) {
return "mozilla::jni::Throwable::LocalRef";
}
return "mozilla::jni::Object::LocalRef";
}
/**
* On failure, the generated method returns a null-esque value. This helper method gets the
* appropriate failure return value for a given Java return type, plus a leading space.
* Get the JNI class descriptor corresponding to the provided type parameter.
*
* @param type Java return type of method being generated
* @return String representation of the failure return value to be used in the generated code.
* @param type Class to determine the corresponding JNI descriptor for.
* @return Class descripor as a String
*/
public static String getFailureReturnForType(Class<?> type) {
String name = type.getCanonicalName();
if (sFailureReturns.containsKey(name)) {
return sFailureReturns.get(name);
public static String getClassDescriptor(Class<?> type) {
final String name = type.getName().replace('.', '/');
if (CLASS_DESCRIPTORS.containsKey(name)) {
return CLASS_DESCRIPTORS.get(name);
}
return " nullptr";
if (type.isArray()) {
// Array names are already in class descriptor form.
return name;
}
return "L" + name + ';';
}
/**
* Helper method to get the type signature for methods, given argument and return type.
* Allows for the near-identical logic needed for constructors and methods to be shared.
* (Alas, constructor does not extend method)
* Get the JNI signaure for a member.
*
* @param arguments Argument types of the underlying method.
* @param returnType Return type of the underlying method.
* @return The canonical Java type string for the method. eg. (IIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;
* @param member Member to get the signature for.
* @return JNI signature as a string
*/
private static String getTypeSignatureInternal(Class<?>[] arguments, Class<?> returnType) {
StringBuilder sb = new StringBuilder();
sb.append('(');
// For each argument, write its signature component to the buffer..
for (int i = 0; i < arguments.length; i++) {
writeTypeSignature(sb, arguments[i]);
}
sb.append(')');
// Write the return value's signature..
writeTypeSignature(sb, returnType);
return sb.toString();
public static String getSignature(Member member) {
return member instanceof Field ? getSignature((Field) member) :
member instanceof Method ? getSignature((Method) member) :
getSignature((Constructor<?>) member);
}
/**
* Get the canonical JNI type signature for a Field.
* Get the JNI signaure for a field.
*
* @param aField The field to generate a signature for.
* @return The canonical JNI type signature for this method.
* @param member Field to get the signature for.
* @return JNI signature as a string
*/
protected static String getTypeSignatureStringForField(Field aField) {
StringBuilder sb = new StringBuilder();
writeTypeSignature(sb, aField.getType());
return sb.toString();
public static String getSignature(Field member) {
return getClassDescriptor(member.getType());
}
/**
* Get the canonical JNI type signature for a method.
*
* @param aMethod The method to generate a signature for.
* @return The canonical JNI type signature for this method.
*/
protected static String getTypeSignatureStringForMethod(Method aMethod) {
Class<?>[] arguments = aMethod.getParameterTypes();
Class<?> returnType = aMethod.getReturnType();
return getTypeSignatureInternal(arguments, returnType);
}
/**
* Get the canonical JNI type signature for a Constructor.
*
* @param aConstructor The Constructor to generate a signature for.
* @return The canonical JNI type signature for this method.
*/
protected static String getTypeSignatureStringForConstructor(Constructor<?> aConstructor) {
Class<?>[] arguments = aConstructor.getParameterTypes();
return getTypeSignatureInternal(arguments, Void.class);
}
public static String getTypeSignatureStringForMember(Member aMember) {
if (aMember instanceof Method) {
return getTypeSignatureStringForMethod((Method) aMember);
} else if (aMember instanceof Field) {
return getTypeSignatureStringForField((Field) aMember);
} else {
return getTypeSignatureStringForConstructor((Constructor<?>) aMember);
}
}
public static String getTypeSignatureStringForClass(Class<?> clazz) {
return clazz.getCanonicalName().replace('.', '/');
}
public static String getTypeSignatureString(Constructor<?> aConstructor) {
Class<?>[] arguments = aConstructor.getParameterTypes();
StringBuilder sb = new StringBuilder();
sb.append('(');
// For each argument, write its signature component to the buffer..
for (int i = 0; i < arguments.length; i++) {
writeTypeSignature(sb, arguments[i]);
}
// Constructors always return Void.
sb.append(")V");
return sb.toString();
}
/**
* Helper method used by getTypeSignatureStringForMethod to build the signature. Write the subsignature
* of a given type into the buffer.
*
* @param sb The buffer to write into.
* @param c The type of the element to write the subsignature of.
*/
private static void writeTypeSignature(StringBuilder sb, Class<?> c) {
String name = Utils.getTypeSignatureStringForClass(c);
// Determine if this is an array type and, if so, peel away the array operators..
int len = name.length();
while (name.endsWith("[]")) {
sb.append('[');
name = name.substring(0, len - 2);
len = len - 2;
}
if (c.isArray()) {
c = c.getComponentType();
}
Class<?> containerClass = c.getDeclaringClass();
if (containerClass != null) {
// Is an inner class. Add the $ symbol.
final int lastSlash = name.lastIndexOf('/');
name = name.substring(0, lastSlash) + '$' + name.substring(lastSlash+1);
}
// Look in the hashmap for the remainder...
if (sCanonicalSignatureParts.containsKey(name)) {
// It was a primitive type, so lookup was a success.
sb.append(sCanonicalSignatureParts.get(name));
} else {
// It was a reference type - generate.
sb.append('L');
sb.append(name);
sb.append(';');
}
}
/**
* Produces a C method signature, sans semicolon, for the given Java Method. Useful for both
* generating header files and method bodies.
*
* @param aArgumentTypes Argument types of the Java method being wrapped.
* @param aReturnType Return type of the Java method being wrapped.
* @param aCMethodName Name of the method to generate in the C++ class.
* @param aCClassName Name of the C++ class into which the method is declared.
* @return The C++ method implementation signature for the method described.
*/
public static String getCImplementationMethodSignature(Class<?>[] aArgumentTypes, Class<?> aReturnType,
String aCMethodName, String aCClassName, boolean aNarrowChars, boolean aCatchException) {
StringBuilder retBuffer = new StringBuilder();
retBuffer.append(getCReturnType(aReturnType, aNarrowChars));
retBuffer.append(' ');
retBuffer.append(aCClassName);
retBuffer.append("::");
retBuffer.append(aCMethodName);
retBuffer.append('(');
// Write argument types...
for (int aT = 0; aT < aArgumentTypes.length; aT++) {
retBuffer.append(getCParameterType(aArgumentTypes[aT], aNarrowChars));
retBuffer.append(" a");
// We, imaginatively, call our arguments a1, a2, a3...
// The only way to preserve the names from Java would be to parse the
// Java source, which would be computationally hard.
retBuffer.append(aT);
if (aT != aArgumentTypes.length - 1) {
retBuffer.append(", ");
}
}
if (aCatchException) {
if (aArgumentTypes.length > 0) {
retBuffer.append(", ");
}
retBuffer.append("nsresult* aResult");
}
retBuffer.append(')');
return retBuffer.toString();
}
/**
* Produces a C method signature, sans semicolon, for the given Java Method. Useful for both
* generating header files and method bodies.
*
* @param aArgumentTypes Argument types of the Java method being wrapped.
* @param aArgumentAnnotations The annotations on the Java method arguments. Used to specify
* default values etc.
* @param aReturnType Return type of the Java method being wrapped.
* @param aCMethodName Name of the method to generate in the C++ class.
* @param aCClassName Name of the C++ class into which the method is declared.e
* @param aIsStaticStub true if the generated C++ method should be static, false otherwise.
* @return The generated C++ header method signature for the method described.
*/
public static String getCHeaderMethodSignature(Class<?>[] aArgumentTypes, Annotation[][] aArgumentAnnotations, Class<?> aReturnType,
String aCMethodName, String aCClassName, boolean aIsStaticStub, boolean aNarrowChars, boolean aCatchException) {
StringBuilder retBuffer = new StringBuilder();
// Add the static keyword, if applicable.
if (aIsStaticStub) {
retBuffer.append("static ");
}
// Write return type..
retBuffer.append(getCReturnType(aReturnType, aNarrowChars));
retBuffer.append(' ');
retBuffer.append(aCMethodName);
retBuffer.append('(');
// Write argument types...
for (int aT = 0; aT < aArgumentTypes.length; aT++) {
retBuffer.append(getCParameterType(aArgumentTypes[aT], aNarrowChars));
retBuffer.append(" a");
// We, imaginatively, call our arguments a1, a2, a3...
// The only way to preserve the names from Java would be to parse the
// Java source, which would be computationally hard.
retBuffer.append(aT);
// Append the default value, if there is one..
retBuffer.append(getDefaultValueString(aArgumentTypes[aT], aArgumentAnnotations[aT]));
if (aT != aArgumentTypes.length - 1) {
retBuffer.append(", ");
}
}
if (aCatchException) {
if (aArgumentTypes.length > 0) {
retBuffer.append(", ");
}
retBuffer.append("nsresult* aResult = nullptr");
}
retBuffer.append(')');
return retBuffer.toString();
}
/**
* If the given Annotation[] contains an OptionalGeneratedParameter annotation then return a
* string assigning an argument of type aArgumentType to the default value for that type.
* Otherwise, return the empty string.
*
* @param aArgumentType The type of the argument to consider.
* @param aArgumentAnnotations The annotations on the argument to consider.
* @return An appropriate string to append to the signature of this argument assigning it to a
* default value (Or not, as applicable).
*/
public static String getDefaultValueString(Class<?> aArgumentType, Annotation[] aArgumentAnnotations) {
for (int i = 0; i < aArgumentAnnotations.length; i++) {
Class<? extends Annotation> annotationType = aArgumentAnnotations[i].annotationType();
final String annotationTypeName = annotationType.getName();
if (annotationTypeName.equals("org.mozilla.gecko.mozglue.generatorannotations.OptionalGeneratedParameter")) {
return " = " + getDefaultParameterValueForType(aArgumentType);
}
}
return "";
}
/**
* Helper method to return an appropriate default parameter value for an argument of a given type.
* The lookup table contains values for primitive types and strings. All other object types default
* to null pointers.
*
* @param aArgumentType The parameter type for which a default value is desired.
* @return An appropriate string representation of the default value selected, for use in generated
* C++ code.
*/
private static String getDefaultParameterValueForType(Class<?> aArgumentType) {
String typeName = aArgumentType.getCanonicalName();
if (sDefaultParameterValues.containsKey(typeName)) {
return sDefaultParameterValues.get(typeName);
} else if (isCharSequence(aArgumentType)) {
return "EmptyString()";
} else {
return "nullptr";
}
}
/**
* Helper method that returns the number of reference types in the arguments of m.
*
* @param aArgs The method arguments to consider.
* @return How many of the arguments of m are nonprimitive.
*/
public static int enumerateReferenceArguments(Class<?>[] aArgs) {
int ret = 0;
for (int i = 0; i < aArgs.length; i++) {
String name = aArgs[i].getCanonicalName();
if (!sBasicCTypes.containsKey(name)) {
ret++;
}
}
return ret;
}
/**
* Helper method that returns true iff the given method has a string argument.
*
* @param m The method to consider.
* @return True if the given method has a string argument, false otherwise.
*/
public static boolean hasStringArgument(Method m) {
Class<?>[] args = m.getParameterTypes();
private static String getSignature(Class<?>[] args, Class<?> ret) {
final StringBuilder sig = new StringBuilder("(");
for (int i = 0; i < args.length; i++) {
if (isCharSequence(args[i])) {
return true;
}
sig.append(getClassDescriptor(args[i]));
}
return false;
return sig.append(')').append(getClassDescriptor(ret)).toString();
}
/**
* Write the argument array assignment line for the given argument type. Does not support array
* types.
* Get the JNI signaure for a method.
*
* @param type Type of this argument according to the target Java method's signature.
* @param argName Wrapper function argument name corresponding to this argument.
* @param member Method to get the signature for.
* @return JNI signature as a string
*/
public static String getArrayArgumentMashallingLine(Class<?> type, String argName) {
StringBuilder sb = new StringBuilder();
String name = type.getCanonicalName();
if (sCanonicalSignatureParts.containsKey(name)) {
sb.append(sCanonicalSignatureParts.get(name).toLowerCase());
sb.append(" = ").append(argName).append(";\n");
} else {
if (isCharSequence(type)) {
sb.append("l = AndroidBridge::NewJavaString(env, ").append(argName).append(");\n");
} else {
sb.append("l = ").append(argName).append(";\n");
}
}
return sb.toString();
public static String getSignature(Method member) {
return getSignature(member.getParameterTypes(), member.getReturnType());
}
/**
* Returns true if the type provided is an object type. Returns false otherwise
* Get the JNI signaure for a constructor.
*
* @param aType The type to consider.
* @return true if the method provided is an object type, false otherwise.
* @param member Constructor to get the signature for.
* @return JNI signature as a string
*/
public static boolean isObjectType(Class<?> aType) {
return !sBasicCTypes.containsKey(aType.getCanonicalName());
public static String getSignature(Constructor<?> member) {
return getSignature(member.getParameterTypes(), void.class);
}
/**
* For a given Java class, get the name of the value in C++ which holds a reference to it.
* Get the C++ name for a member.
*
* @param aClass Target Java class.
* @return The name of the C++ jclass entity referencing the given class.
* @param member Member to get the name for.
* @return JNI name as a string
*/
public static String getClassReferenceName(Class<?> aClass) {
String className = aClass.getSimpleName();
return 'm' + className + "Class";
public static String getNativeName(Member member) {
final String name = getMemberName(member);
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
/**
* Generate a line to get a global reference to the Java class given.
* Get the JNI name for a member.
*
* @param aClass The target Java class.
* @return The generated code to populate the reference to the class.
* @param member Member to get the name for.
* @return JNI name as a string
*/
public static String getStartupLineForClass(Class<?> aClass) {
StringBuilder sb = new StringBuilder();
sb.append(" ");
sb.append(getClassReferenceName(aClass));
sb.append(" = AndroidBridge::GetClassGlobalRef(env, \"");
String name = Utils.getTypeSignatureStringForClass(aClass);
Class<?> containerClass = aClass.getDeclaringClass();
if (containerClass != null) {
// Is an inner class. Add the $ symbol.
final int lastSlash = name.lastIndexOf('/');
name = name.substring(0, lastSlash) + '$' + name.substring(lastSlash+1);
public static String getMemberName(Member member) {
if (member instanceof Constructor) {
return "<init>";
}
sb.append(name);
sb.append("\");\n");
return sb.toString();
return member.getName();
}
/**
* Helper method to determine if this object implements CharSequence
* @param aClass Class to check for CharSequence-esqueness
* @return True if the given class implements CharSequence, false otherwise.
* Determine if a member is declared static.
*
* @param member The Member to check.
* @return true if the member is declared static, false otherwise.
*/
public static boolean isCharSequence(Class<?> aClass) {
if (aClass.getCanonicalName().equals("java.lang.CharSequence")) {
return true;
}
Class<?>[] interfaces = aClass.getInterfaces();
for (Class<?> c : interfaces) {
if (c.getCanonicalName().equals("java.lang.CharSequence")) {
return true;
}
}
return false;
public static boolean isStatic(final Member member) {
return Modifier.isStatic(member.getModifiers());
}
/**
* Helper method to read the modifier bits of the given method to determine if it is static.
* @param aMember The Member to check.
* @return true of the method is declared static, false otherwise.
* Determine if a member is declared final.
*
* @param member The Member to check.
* @return true if the member is declared final, false otherwise.
*/
public static boolean isMemberStatic(Member aMember) {
int aMethodModifiers = aMember.getModifiers();
return Modifier.isStatic(aMethodModifiers);
}
/**
* Helper method to read the modifier bits of the given method to determine if it is static.
* @param aMember The Member to check.
* @return true of the method is declared static, false otherwise.
*/
public static boolean isMemberFinal(Member aMember) {
int aMethodModifiers = aMember.getModifiers();
return Modifier.isFinal(aMethodModifiers);
public static boolean isFinal(final Member member) {
return Modifier.isFinal(member.getModifiers());
}
}

View File

@ -2493,7 +2493,7 @@ ContentParent::RecvGetShowPasswordSetting(bool* showPassword)
#ifdef MOZ_WIDGET_ANDROID
NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
*showPassword = mozilla::widget::android::GeckoAppShell::GetShowPasswordSetting();
*showPassword = mozilla::widget::GeckoAppShell::GetShowPasswordSetting();
#endif
return true;
}

View File

@ -24,25 +24,25 @@
using namespace mozilla;
using namespace mozilla::gl;
using namespace mozilla::widget::android::sdk;
using namespace mozilla::widget::sdk;
namespace mozilla {
static MediaCodec* CreateDecoder(JNIEnv* aEnv, const char* aMimeType)
static MediaCodec::LocalRef CreateDecoder(const char* aMimeType)
{
if (!aMimeType) {
return nullptr;
}
jobject decoder = MediaCodec::CreateDecoderByType(nsCString(aMimeType));
return new MediaCodec(decoder, aEnv);
MediaCodec::LocalRef codec;
NS_ENSURE_SUCCESS(MediaCodec::CreateDecoderByType(aMimeType, &codec), nullptr);
return codec;
}
class VideoDataDecoder : public MediaCodecDataDecoder {
public:
VideoDataDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
MediaFormat* aFormat, MediaDataDecoderCallback* aCallback,
MediaFormat::Param aFormat, MediaDataDecoderCallback* aCallback,
layers::ImageContainer* aImageContainer)
: MediaCodecDataDecoder(MediaData::Type::VIDEO_DATA, aConfig.mime_type, aFormat, aCallback)
, mImageContainer(aImageContainer)
@ -108,7 +108,7 @@ public:
return eglImage;
}
virtual nsresult PostOutput(BufferInfo* aInfo, MediaFormat* aFormat, Microseconds aDuration) MOZ_OVERRIDE {
virtual nsresult PostOutput(BufferInfo::Param aInfo, MediaFormat::Param aFormat, Microseconds aDuration) MOZ_OVERRIDE {
VideoInfo videoInfo;
videoInfo.mDisplay = nsIntSize(mConfig.display_width, mConfig.display_height);
@ -143,13 +143,23 @@ public:
layers::EGLImageImage* typedImg = static_cast<layers::EGLImageImage*>(img.get());
typedImg->SetData(data);
bool isSync = !!(MediaCodec::getBUFFER_FLAG_SYNC_FRAME() & aInfo->getFlags());
nsresult rv;
int32_t flags;
NS_ENSURE_SUCCESS(rv = aInfo->Flags(&flags), rv);
nsRefPtr<VideoData> v = VideoData::CreateFromImage(videoInfo, mImageContainer, aInfo->getOffset(),
aInfo->getPresentationTimeUs(),
bool isSync = !!(flags & MediaCodec::BUFFER_FLAG_SYNC_FRAME);
int32_t offset;
NS_ENSURE_SUCCESS(rv = aInfo->Offset(&offset), rv);
int64_t presentationTimeUs;
NS_ENSURE_SUCCESS(rv = aInfo->PresentationTimeUs(&presentationTimeUs), rv);
nsRefPtr<VideoData> v = VideoData::CreateFromImage(videoInfo, mImageContainer, offset,
presentationTimeUs,
aDuration,
img, isSync,
aInfo->getPresentationTimeUs(),
presentationTimeUs,
gfx::IntRect(0, 0,
mConfig.display_width,
mConfig.display_height));
@ -174,23 +184,53 @@ protected:
};
class AudioDataDecoder : public MediaCodecDataDecoder {
private:
uint8_t csd0[2];
public:
AudioDataDecoder(const char* aMimeType, MediaFormat* aFormat, MediaDataDecoderCallback* aCallback)
: MediaCodecDataDecoder(MediaData::Type::AUDIO_DATA, aMimeType, aFormat, aCallback)
AudioDataDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, MediaFormat::Param aFormat, MediaDataDecoderCallback* aCallback)
: MediaCodecDataDecoder(MediaData::Type::AUDIO_DATA, aConfig.mime_type, aFormat, aCallback)
{
JNIEnv* env = GetJNIForThread();
jni::Object::LocalRef buffer(env);
NS_ENSURE_SUCCESS_VOID(aFormat->GetByteBuffer(NS_LITERAL_STRING("csd-0"), &buffer));
if (!buffer) {
csd0[0] = (*aConfig.audio_specific_config)[0];
csd0[1] = (*aConfig.audio_specific_config)[1];
buffer = jni::Object::LocalRef::Adopt(env, env->NewDirectByteBuffer(csd0, 2));
NS_ENSURE_SUCCESS_VOID(aFormat->SetByteBuffer(NS_LITERAL_STRING("csd-0"), buffer));
}
}
nsresult Output(BufferInfo* aInfo, void* aBuffer, MediaFormat* aFormat, Microseconds aDuration) {
nsresult Output(BufferInfo::Param aInfo, void* aBuffer, MediaFormat::Param aFormat, Microseconds aDuration) {
// The output on Android is always 16-bit signed
uint32_t numChannels = aFormat->GetInteger(NS_LITERAL_CSTRING("channel-count"));
uint32_t sampleRate = aFormat->GetInteger(NS_LITERAL_CSTRING("sample-rate"));
uint32_t numFrames = (aInfo->getSize() / numChannels) / 2;
nsresult rv;
int32_t numChannels;
NS_ENSURE_SUCCESS(rv =
aFormat->GetInteger(NS_LITERAL_STRING("channel-count"), &numChannels), rv);
AudioDataValue* audio = new AudioDataValue[aInfo->getSize()];
PodCopy(audio, static_cast<AudioDataValue*>(aBuffer), aInfo->getSize());
int32_t sampleRate;
NS_ENSURE_SUCCESS(rv =
aFormat->GetInteger(NS_LITERAL_STRING("sample-rate"), &sampleRate), rv);
nsRefPtr<AudioData> data = new AudioData(aInfo->getOffset(), aInfo->getPresentationTimeUs(),
int32_t size;
NS_ENSURE_SUCCESS(rv = aInfo->Size(&size), rv);
const int32_t numFrames = (size / numChannels) / 2;
AudioDataValue* audio = new AudioDataValue[size];
PodCopy(audio, static_cast<AudioDataValue*>(aBuffer), size);
int32_t offset;
NS_ENSURE_SUCCESS(rv = aInfo->Offset(&offset), rv);
int64_t presentationTimeUs;
NS_ENSURE_SUCCESS(rv = aInfo->PresentationTimeUs(&presentationTimeUs), rv);
nsRefPtr<AudioData> data = new AudioData(offset, presentationTimeUs,
aDuration,
numFrames,
audio,
@ -203,11 +243,7 @@ public:
bool AndroidDecoderModule::SupportsAudioMimeType(const char* aMimeType) {
JNIEnv* env = GetJNIForThread();
MediaCodec* decoder = CreateDecoder(env, aMimeType);
bool supports = (decoder != nullptr);
delete decoder;
return supports;
return static_cast<bool>(CreateDecoder(aMimeType));
}
already_AddRefed<MediaDataDecoder>
@ -218,19 +254,13 @@ AndroidDecoderModule::CreateVideoDecoder(
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback)
{
jobject jFormat = MediaFormat::CreateVideoFormat(nsCString(aConfig.mime_type),
aConfig.display_width,
aConfig.display_height);
MediaFormat::LocalRef format;
if (!jFormat) {
return nullptr;
}
MediaFormat* format = MediaFormat::Wrap(jFormat);
if (!format) {
return nullptr;
}
NS_ENSURE_SUCCESS(MediaFormat::CreateVideoFormat(
aConfig.mime_type,
aConfig.display_width,
aConfig.display_height,
&format), nullptr);
nsRefPtr<MediaDataDecoder> decoder =
new VideoDataDecoder(aConfig, format, aCallback, aImageContainer);
@ -245,34 +275,16 @@ AndroidDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig&
{
MOZ_ASSERT(aConfig.bits_per_sample == 16, "We only handle 16-bit audio!");
jobject jFormat = MediaFormat::CreateAudioFormat(nsCString(aConfig.mime_type),
aConfig.samples_per_second,
aConfig.channel_count);
MediaFormat::LocalRef format;
if (jFormat == nullptr)
return nullptr;
MediaFormat* format = MediaFormat::Wrap(jFormat);
if(format == nullptr)
return nullptr;
JNIEnv* env = GetJNIForThread();
if (!format->GetByteBuffer(NS_LITERAL_CSTRING("csd-0"))) {
uint8_t* csd0 = new uint8_t[2];
csd0[0] = (*aConfig.audio_specific_config)[0];
csd0[1] = (*aConfig.audio_specific_config)[1];
jobject buffer = env->NewDirectByteBuffer(csd0, 2);
format->SetByteBuffer(NS_LITERAL_CSTRING("csd-0"), buffer);
env->DeleteLocalRef(buffer);
}
NS_ENSURE_SUCCESS(MediaFormat::CreateAudioFormat(
aConfig.mime_type,
aConfig.samples_per_second,
aConfig.channel_count,
&format), nullptr);
nsRefPtr<MediaDataDecoder> decoder =
new AudioDataDecoder(aConfig.mime_type, format, aCallback);
new AudioDataDecoder(aConfig, format, aCallback);
return decoder.forget();
@ -286,7 +298,7 @@ nsresult AndroidDecoderModule::Shutdown()
MediaCodecDataDecoder::MediaCodecDataDecoder(MediaData::Type aType,
const char* aMimeType,
MediaFormat* aFormat,
MediaFormat::Param aFormat,
MediaDataDecoderCallback* aCallback)
: mType(aType)
, mMimeType(strdup(aMimeType))
@ -304,55 +316,28 @@ MediaCodecDataDecoder::MediaCodecDataDecoder(MediaData::Type aType,
MediaCodecDataDecoder::~MediaCodecDataDecoder()
{
JNIEnv* env = GetJNIForThread();
Shutdown();
if (mInputBuffers) {
env->DeleteGlobalRef(mInputBuffers);
mInputBuffers = nullptr;
}
if (mOutputBuffers) {
env->DeleteGlobalRef(mOutputBuffers);
mOutputBuffers = nullptr;
}
}
nsresult MediaCodecDataDecoder::Init()
{
return InitDecoder();
return InitDecoder(nullptr);
}
nsresult MediaCodecDataDecoder::InitDecoder(jobject aSurface)
nsresult MediaCodecDataDecoder::InitDecoder(Surface::Param aSurface)
{
JNIEnv* env = GetJNIForThread();
mDecoder = CreateDecoder(env, mMimeType);
mDecoder = CreateDecoder(mMimeType);
if (!mDecoder) {
mCallback->Error();
return NS_ERROR_FAILURE;
}
nsresult res;
mDecoder->Configure(mFormat->wrappedObject(), aSurface, nullptr, 0, &res);
if (NS_FAILED(res)) {
return res;
}
nsresult rv;
NS_ENSURE_SUCCESS(rv = mDecoder->Configure(mFormat, aSurface, nullptr, 0), rv);
NS_ENSURE_SUCCESS(rv = mDecoder->Start(), rv);
mDecoder->Start(&res);
if (NS_FAILED(res)) {
return res;
}
res = ResetInputBuffers();
if (NS_FAILED(res)) {
return res;
}
res = ResetOutputBuffers();
if (NS_FAILED(res)) {
return res;
}
NS_ENSURE_SUCCESS(rv = ResetInputBuffers(), rv);
NS_ENSURE_SUCCESS(rv = ResetOutputBuffers(), rv);
NS_NewNamedThread("MC Decoder", getter_AddRefs(mThread),
NS_NewRunnableMethod(this, &MediaCodecDataDecoder::DecoderLoop));
@ -377,10 +362,10 @@ void MediaCodecDataDecoder::DecoderLoop()
bool draining = false;
bool waitingEOF = false;
JNIEnv* env = GetJNIForThread();
AutoLocalJNIFrame frame(GetJNIForThread(), 1);
mp4_demuxer::MP4Sample* sample = nullptr;
nsAutoPtr<MediaFormat> outputFormat;
MediaFormat::LocalRef outputFormat(frame.GetEnv());
nsresult res;
for (;;) {
@ -420,61 +405,69 @@ void MediaCodecDataDecoder::DecoderLoop()
if (draining && !waitingEOF) {
MOZ_ASSERT(!sample, "Shouldn't have a sample when pushing EOF frame");
int inputIndex = mDecoder->DequeueInputBuffer(DECODER_TIMEOUT, &res);
int32_t inputIndex;
res = mDecoder->DequeueInputBuffer(DECODER_TIMEOUT, &inputIndex);
HANDLE_DECODER_ERROR();
if (inputIndex >= 0) {
mDecoder->QueueInputBuffer(inputIndex, 0, 0, 0, MediaCodec::getBUFFER_FLAG_END_OF_STREAM(), &res);
res = mDecoder->QueueInputBuffer(inputIndex, 0, 0, 0, MediaCodec::BUFFER_FLAG_END_OF_STREAM);
HANDLE_DECODER_ERROR();
waitingEOF = true;
}
}
if (sample) {
// We have a sample, try to feed it to the decoder
int inputIndex = mDecoder->DequeueInputBuffer(DECODER_TIMEOUT, &res);
int inputIndex;
res = mDecoder->DequeueInputBuffer(DECODER_TIMEOUT, &inputIndex);
HANDLE_DECODER_ERROR();
if (inputIndex >= 0) {
jobject buffer = env->GetObjectArrayElement(mInputBuffers, inputIndex);
void* directBuffer = env->GetDirectBufferAddress(buffer);
auto buffer = jni::Object::LocalRef::Adopt(
frame.GetEnv()->GetObjectArrayElement(mInputBuffers.Get(), inputIndex));
void* directBuffer = frame.GetEnv()->GetDirectBufferAddress(buffer.Get());
// We're feeding this to the decoder, so remove it from the queue
mMonitor.Lock();
mQueue.pop();
mMonitor.Unlock();
MOZ_ASSERT(env->GetDirectBufferCapacity(buffer) >= sample->size,
MOZ_ASSERT(frame.GetEnv()->GetDirectBufferCapacity(buffer.Get()) >= sample->size,
"Decoder buffer is not large enough for sample");
{
// We're feeding this to the decoder, so remove it from the queue
MonitorAutoLock lock(mMonitor);
mQueue.pop();
}
PodCopy((uint8_t*)directBuffer, sample->data, sample->size);
mDecoder->QueueInputBuffer(inputIndex, 0, sample->size, sample->composition_timestamp, 0, &res);
res = mDecoder->QueueInputBuffer(inputIndex, 0, sample->size,
sample->composition_timestamp, 0);
HANDLE_DECODER_ERROR();
mDurations.push(sample->duration);
delete sample;
sample = nullptr;
outputDone = false;
env->DeleteLocalRef(buffer);
}
}
if (!outputDone) {
BufferInfo bufferInfo;
int outputStatus = mDecoder->DequeueOutputBuffer(bufferInfo.wrappedObject(), DECODER_TIMEOUT, &res);
BufferInfo::LocalRef bufferInfo;
res = BufferInfo::New(&bufferInfo);
HANDLE_DECODER_ERROR();
if (outputStatus == MediaCodec::getINFO_TRY_AGAIN_LATER()) {
int32_t outputStatus;
res = mDecoder->DequeueOutputBuffer(bufferInfo, DECODER_TIMEOUT, &outputStatus);
HANDLE_DECODER_ERROR();
if (outputStatus == MediaCodec::INFO_TRY_AGAIN_LATER) {
// We might want to call mCallback->InputExhausted() here, but there seems to be
// some possible bad interactions here with the threading
} else if (outputStatus == MediaCodec::getINFO_OUTPUT_BUFFERS_CHANGED()) {
} else if (outputStatus == MediaCodec::INFO_OUTPUT_BUFFERS_CHANGED) {
res = ResetOutputBuffers();
HANDLE_DECODER_ERROR();
} else if (outputStatus == MediaCodec::getINFO_OUTPUT_FORMAT_CHANGED()) {
outputFormat = new MediaFormat(mDecoder->GetOutputFormat(), GetJNIForThread());
} else if (outputStatus == MediaCodec::INFO_OUTPUT_FORMAT_CHANGED) {
res = mDecoder->GetOutputFormat(ReturnTo(&outputFormat));
HANDLE_DECODER_ERROR();
} else if (outputStatus < 0) {
NS_WARNING("unknown error from decoder!");
mCallback->Error();
@ -482,8 +475,12 @@ void MediaCodecDataDecoder::DecoderLoop()
// Don't break here just in case it's recoverable. If it's not, others stuff will fail later and
// we'll bail out.
} else {
int32_t flags;
res = bufferInfo->Flags(&flags);
HANDLE_DECODER_ERROR();
// We have a valid buffer index >= 0 here
if (bufferInfo.getFlags() & MediaCodec::getBUFFER_FLAG_END_OF_STREAM()) {
if (flags & MediaCodec::BUFFER_FLAG_END_OF_STREAM) {
if (draining) {
draining = false;
waitingEOF = false;
@ -511,21 +508,18 @@ void MediaCodecDataDecoder::DecoderLoop()
mDurations.pop();
}
jobject buffer = env->GetObjectArrayElement(mOutputBuffers, outputStatus);
auto buffer = jni::Object::LocalRef::Adopt(
frame.GetEnv()->GetObjectArrayElement(mOutputBuffers.Get(), outputStatus));
if (buffer) {
// The buffer will be null on Android L if we are decoding to a Surface
void* directBuffer = env->GetDirectBufferAddress(buffer);
Output(&bufferInfo, directBuffer, outputFormat, duration);
void* directBuffer = frame.GetEnv()->GetDirectBufferAddress(buffer.Get());
Output(bufferInfo, directBuffer, outputFormat, duration);
}
// The Surface will be updated at this point (for video)
mDecoder->ReleaseOutputBuffer(outputStatus, true);
PostOutput(&bufferInfo, outputFormat, duration);
if (buffer) {
env->DeleteLocalRef(buffer);
}
PostOutput(bufferInfo, outputFormat, duration);
}
}
}
@ -533,10 +527,9 @@ void MediaCodecDataDecoder::DecoderLoop()
Cleanup();
// We're done
mMonitor.Lock();
MonitorAutoLock lock(mMonitor);
mStopping = false;
mMonitor.Notify();
mMonitor.Unlock();
}
void MediaCodecDataDecoder::ClearQueue()
@ -561,36 +554,12 @@ nsresult MediaCodecDataDecoder::Input(mp4_demuxer::MP4Sample* aSample) {
nsresult MediaCodecDataDecoder::ResetInputBuffers()
{
JNIEnv* env = GetJNIForThread();
if (mInputBuffers) {
env->DeleteGlobalRef(mInputBuffers);
}
nsresult res;
mInputBuffers = (jobjectArray) env->NewGlobalRef(mDecoder->GetInputBuffers(&res));
if (NS_FAILED(res)) {
return res;
}
return NS_OK;
return mDecoder->GetInputBuffers(ReturnTo(&mInputBuffers));
}
nsresult MediaCodecDataDecoder::ResetOutputBuffers()
{
JNIEnv* env = GetJNIForThread();
if (mOutputBuffers) {
env->DeleteGlobalRef(mOutputBuffers);
}
nsresult res;
mOutputBuffers = (jobjectArray) env->NewGlobalRef(mDecoder->GetOutputBuffers(&res));
if (NS_FAILED(res)) {
return res;
}
return NS_OK;
return mDecoder->GetOutputBuffers(ReturnTo(&mOutputBuffers));
}
nsresult MediaCodecDataDecoder::Flush() {

View File

@ -17,18 +17,6 @@ namespace mozilla {
typedef std::queue<mp4_demuxer::MP4Sample*> SampleQueue;
namespace widget {
namespace android {
namespace sdk {
class MediaCodec;
class MediaFormat;
class ByteBuffer;
}
}
}
class MediaCodecDataDecoder;
class AndroidDecoderModule : public PlatformDecoderModule {
public:
virtual nsresult Shutdown() MOZ_OVERRIDE;
@ -57,7 +45,7 @@ public:
MediaCodecDataDecoder(MediaData::Type aType,
const char* aMimeType,
mozilla::widget::android::sdk::MediaFormat* aFormat,
widget::sdk::MediaFormat::Param aFormat,
MediaDataDecoderCallback* aCallback);
virtual ~MediaCodecDataDecoder();
@ -74,14 +62,14 @@ protected:
MediaData::Type mType;
nsAutoPtr<char> mMimeType;
nsAutoPtr<mozilla::widget::android::sdk::MediaFormat> mFormat;
widget::sdk::MediaFormat::GlobalRef mFormat;
MediaDataDecoderCallback* mCallback;
nsAutoPtr<mozilla::widget::android::sdk::MediaCodec> mDecoder;
widget::sdk::MediaCodec::GlobalRef mDecoder;
jobjectArray mInputBuffers;
jobjectArray mOutputBuffers;
jni::ObjectArray::GlobalRef mInputBuffers;
jni::ObjectArray::GlobalRef mOutputBuffers;
nsCOMPtr<nsIThread> mThread;
@ -94,10 +82,10 @@ protected:
SampleQueue mQueue;
std::queue<Microseconds> mDurations;
virtual nsresult InitDecoder(jobject aSurface = nullptr);
virtual nsresult InitDecoder(widget::sdk::Surface::Param aSurface);
virtual nsresult Output(mozilla::widget::android::sdk::BufferInfo* aInfo, void* aBuffer, mozilla::widget::android::sdk::MediaFormat* aFormat, Microseconds aDuration) { return NS_OK; }
virtual nsresult PostOutput(mozilla::widget::android::sdk::BufferInfo* aInfo, mozilla::widget::android::sdk::MediaFormat* aFormat, Microseconds aDuration) { return NS_OK; }
virtual nsresult Output(widget::sdk::BufferInfo::Param aInfo, void* aBuffer, widget::sdk::MediaFormat::Param aFormat, Microseconds aDuration) { return NS_OK; }
virtual nsresult PostOutput(widget::sdk::BufferInfo::Param aInfo, widget::sdk::MediaFormat::Param aFormat, Microseconds aDuration) { return NS_OK; }
virtual void Cleanup() {};
nsresult ResetInputBuffers();

View File

@ -50,20 +50,17 @@ anp_system_getApplicationDataDirectory()
return anp_system_getApplicationDataDirectory(nullptr);
}
jclass anp_system_loadJavaClass(NPP instance, const char* classNameStr)
jclass anp_system_loadJavaClass(NPP instance, const char* className)
{
LOG("%s", __PRETTY_FUNCTION__);
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
mozilla::PluginPRLibrary* lib = static_cast<mozilla::PluginPRLibrary*>(pinst->GetPlugin()->GetLibrary());
NS_ConvertUTF8toUTF16 className(classNameStr);
nsCString libName;
lib->GetLibraryPath(libName);
nsCString libNameUtf8;
lib->GetLibraryPath(libNameUtf8);
NS_ConvertUTF8toUTF16 libName(libNameUtf8);
return mozilla::widget::android::GeckoAppShell::LoadPluginClass(className, libName);
return mozilla::widget::GeckoAppShell::LoadPluginClass(className, libName).Forget();
}
void anp_system_setPowerState(NPP instance, ANPPowerState powerState)

View File

@ -2269,12 +2269,11 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
}
case kJavaContext_ANPGetValue: {
jobject ret = mozilla::widget::android::GeckoAppShell::GetContext();
auto ret = widget::GeckoAppShell::GetContext();
if (!ret)
return NPERR_GENERIC_ERROR;
int32_t* i = reinterpret_cast<int32_t*>(result);
*i = reinterpret_cast<int32_t>(ret);
*static_cast<jobject*>(result) = ret.Forget();
return NPERR_NO_ERROR;
}

View File

@ -849,7 +849,7 @@ void nsNPAPIPluginInstance::NotifyFullScreen(bool aFullScreen)
SendLifecycleEvent(this, mFullScreen ? kEnterFullScreen_ANPLifecycleAction : kExitFullScreen_ANPLifecycleAction);
if (mFullScreen && mFullScreenOrientation != dom::eScreenOrientation_None) {
mozilla::widget::android::GeckoAppShell::LockScreenOrientation(mFullScreenOrientation);
widget::GeckoAppShell::LockScreenOrientation(mFullScreenOrientation);
}
}
@ -906,11 +906,11 @@ void nsNPAPIPluginInstance::SetFullScreenOrientation(uint32_t orientation)
// We're already fullscreen so immediately apply the orientation change
if (mFullScreenOrientation != dom::eScreenOrientation_None) {
mozilla::widget::android::GeckoAppShell::LockScreenOrientation(mFullScreenOrientation);
widget::GeckoAppShell::LockScreenOrientation(mFullScreenOrientation);
} else if (oldOrientation != dom::eScreenOrientation_None) {
// We applied an orientation when we entered fullscreen, but
// we don't want it anymore
mozilla::widget::android::GeckoAppShell::UnlockScreenOrientation();
widget::GeckoAppShell::UnlockScreenOrientation();
}
}
}

View File

@ -1356,7 +1356,8 @@ void nsPluginInstanceOwner::RemovePluginView()
if (!mInstance || !mJavaView)
return;
mozilla::widget::android::GeckoAppShell::RemovePluginView((jobject)mJavaView, mFullScreen);
widget::GeckoAppShell::RemovePluginView(
jni::Object::Ref::From(jobject(mJavaView)), mFullScreen);
AndroidBridge::GetJNIEnv()->DeleteGlobalRef((jobject)mJavaView);
mJavaView = nullptr;

View File

@ -26,7 +26,7 @@ AndroidLocationProvider::~AndroidLocationProvider()
NS_IMETHODIMP
AndroidLocationProvider::Startup()
{
mozilla::widget::android::GeckoAppShell::EnableLocation(true);
widget::GeckoAppShell::EnableLocation(true);
return NS_OK;
}
@ -42,13 +42,13 @@ AndroidLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
NS_IMETHODIMP
AndroidLocationProvider::Shutdown()
{
mozilla::widget::android::GeckoAppShell::EnableLocation(false);
widget::GeckoAppShell::EnableLocation(false);
return NS_OK;
}
NS_IMETHODIMP
AndroidLocationProvider::SetHighAccuracy(bool enable)
{
mozilla::widget::android::GeckoAppShell::EnableLocationHighAccuracy(enable);
widget::GeckoAppShell::EnableLocationHighAccuracy(enable);
return NS_OK;
}

View File

@ -14,6 +14,6 @@ NS_IMPL_ISUPPORTS(nsHapticFeedback, nsIHapticFeedback)
NS_IMETHODIMP
nsHapticFeedback::PerformSimpleAction(int32_t aType)
{
mozilla::widget::android::GeckoAppShell::PerformHapticFeedback(aType == LongPress);
widget::GeckoAppShell::PerformHapticFeedback(aType == LongPress);
return NS_OK;
}

View File

@ -19,8 +19,9 @@
#include "GLContext.h"
using namespace mozilla;
using namespace mozilla::widget::android;
using namespace mozilla::widget::android::sdk;
using namespace mozilla::jni;
using namespace mozilla::widget;
using namespace mozilla::widget::sdk;
namespace mozilla {
namespace gl {
@ -103,9 +104,7 @@ AndroidSurfaceTexture::Attach(GLContext* aContext, PRIntervalTime aTimeout)
mAttachedContext->MakeCurrent();
aContext->fGenTextures(1, &mTexture);
nsresult res;
mSurfaceTexture->AttachToGLContext(mTexture, &res);
return res;
return mSurfaceTexture->AttachToGLContext(mTexture);
}
nsresult
@ -136,9 +135,8 @@ AndroidSurfaceTexture::Init(GLContext* aContext, GLuint aTexture)
return false;
}
nsresult res;
mSurfaceTexture = new SurfaceTexture(aTexture, &res);
if (NS_FAILED(res)) {
if (NS_WARN_IF(NS_FAILED(
SurfaceTexture::New(aTexture, ReturnTo(&mSurfaceTexture))))) {
return false;
}
@ -148,13 +146,13 @@ AndroidSurfaceTexture::Init(GLContext* aContext, GLuint aTexture)
mAttachedContext = aContext;
mSurface = new Surface(mSurfaceTexture->wrappedObject(), &res);
if (NS_FAILED(res)) {
if (NS_WARN_IF(NS_FAILED(
Surface::New(mSurfaceTexture, ReturnTo(&mSurface))))) {
return false;
}
mNativeWindow = AndroidNativeWindow::CreateFromSurface(GetJNIForThread(),
mSurface->wrappedObject());
mSurface.Get());
MOZ_ASSERT(mNativeWindow, "Failed to create native window from surface");
mID = ++sNextID;
@ -165,8 +163,8 @@ AndroidSurfaceTexture::Init(GLContext* aContext, GLuint aTexture)
AndroidSurfaceTexture::AndroidSurfaceTexture()
: mTexture(0)
, mSurfaceTexture(nullptr)
, mSurface(nullptr)
, mSurfaceTexture()
, mSurface()
, mMonitor("AndroidSurfaceTexture::mContextMonitor")
, mAttachedContext(nullptr)
{
@ -179,7 +177,7 @@ AndroidSurfaceTexture::~AndroidSurfaceTexture()
mFrameAvailableCallback = nullptr;
if (mSurfaceTexture) {
GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture->wrappedObject());
GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
mSurfaceTexture = nullptr;
}
}
@ -195,12 +193,10 @@ AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix)
{
JNIEnv* env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env);
jfloatArray jarray = env->NewFloatArray(16);
auto jarray = FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
mSurfaceTexture->GetTransformMatrix(jarray);
jfloat* array = env->GetFloatArrayElements(jarray, nullptr);
jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
aMatrix._11 = array[0];
aMatrix._12 = array[1];
@ -222,16 +218,16 @@ AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix)
aMatrix._43 = array[14];
aMatrix._44 = array[15];
env->ReleaseFloatArrayElements(jarray, array, 0);
env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
}
void
AndroidSurfaceTexture::SetFrameAvailableCallback(nsIRunnable* aRunnable)
{
if (aRunnable) {
GeckoAppShell::RegisterSurfaceTextureFrameListener(mSurfaceTexture->wrappedObject(), mID);
GeckoAppShell::RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID);
} else {
GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture->wrappedObject());
GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
}
mFrameAvailableCallback = aRunnable;

View File

@ -87,7 +87,8 @@ public:
void NotifyFrameAvailable();
GLuint Texture() { return mTexture; }
jobject JavaSurface() { return mSurface->wrappedObject(); }
const widget::sdk::Surface::Ref& JavaSurface() { return mSurface; }
private:
AndroidSurfaceTexture();
~AndroidSurfaceTexture();
@ -95,8 +96,8 @@ private:
bool Init(GLContext* aContext, GLuint aTexture);
GLuint mTexture;
nsAutoPtr<mozilla::widget::android::sdk::SurfaceTexture> mSurfaceTexture;
nsAutoPtr<mozilla::widget::android::sdk::Surface> mSurface;
widget::sdk::SurfaceTexture::GlobalRef mSurfaceTexture;
widget::sdk::Surface::GlobalRef mSurface;
Monitor mMonitor;
GLContext* mAttachedContext;

View File

@ -14,13 +14,13 @@ namespace hal_impl {
void
StartMonitoringGamepadStatus()
{
mozilla::widget::android::GeckoAppShell::StartMonitoringGamepad();
widget::GeckoAppShell::StartMonitoringGamepad();
}
void
StopMonitoringGamepadStatus()
{
mozilla::widget::android::GeckoAppShell::StopMonitoringGamepad();
widget::GeckoAppShell::StopMonitoringGamepad();
}
} // hal_impl

View File

@ -14,7 +14,6 @@
using namespace mozilla::dom;
using namespace mozilla::hal;
using namespace mozilla::widget::android;
namespace mozilla {
namespace hal_impl {
@ -55,19 +54,19 @@ CancelVibrate(const WindowIdentifier &)
{
// Ignore WindowIdentifier parameter.
mozilla::widget::android::GeckoAppShell::CancelVibrate();
mozilla::widget::GeckoAppShell::CancelVibrate();
}
void
EnableBatteryNotifications()
{
mozilla::widget::android::GeckoAppShell::EnableBatteryNotifications();
mozilla::widget::GeckoAppShell::EnableBatteryNotifications();
}
void
DisableBatteryNotifications()
{
mozilla::widget::android::GeckoAppShell::DisableBatteryNotifications();
mozilla::widget::GeckoAppShell::DisableBatteryNotifications();
}
void
@ -79,13 +78,13 @@ GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
void
EnableNetworkNotifications()
{
mozilla::widget::android::GeckoAppShell::EnableNetworkNotifications();
mozilla::widget::GeckoAppShell::EnableNetworkNotifications();
}
void
DisableNetworkNotifications()
{
mozilla::widget::android::GeckoAppShell::DisableNetworkNotifications();
mozilla::widget::GeckoAppShell::DisableNetworkNotifications();
}
void
@ -97,13 +96,13 @@ GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo)
void
EnableScreenConfigurationNotifications()
{
mozilla::widget::android::GeckoAppShell::EnableScreenOrientationNotifications();
mozilla::widget::GeckoAppShell::EnableScreenOrientationNotifications();
}
void
DisableScreenConfigurationNotifications()
{
mozilla::widget::android::GeckoAppShell::DisableScreenOrientationNotifications();
mozilla::widget::GeckoAppShell::DisableScreenOrientationNotifications();
}
void
@ -149,7 +148,7 @@ LockScreenOrientation(const ScreenOrientation& aOrientation)
case eScreenOrientation_LandscapeSecondary:
case eScreenOrientation_LandscapePrimary | eScreenOrientation_LandscapeSecondary:
case eScreenOrientation_Default:
mozilla::widget::android::GeckoAppShell::LockScreenOrientation(aOrientation);
mozilla::widget::GeckoAppShell::LockScreenOrientation(aOrientation);
return true;
default:
return false;
@ -159,7 +158,7 @@ LockScreenOrientation(const ScreenOrientation& aOrientation)
void
UnlockScreenOrientation()
{
mozilla::widget::android::GeckoAppShell::UnlockScreenOrientation();
mozilla::widget::GeckoAppShell::UnlockScreenOrientation();
}
} // hal_impl

View File

@ -13,12 +13,12 @@ namespace hal_impl {
void
EnableSensorNotifications(SensorType aSensor) {
mozilla::widget::android::GeckoAppShell::EnableSensor(aSensor);
widget::GeckoAppShell::EnableSensor(aSensor);
}
void
DisableSensorNotifications(SensorType aSensor) {
mozilla::widget::android::GeckoAppShell::DisableSensor(aSensor);
widget::GeckoAppShell::DisableSensor(aSensor);
}
} // hal_impl

View File

@ -110,7 +110,7 @@ MessagePump::Run(MessagePump::Delegate* aDelegate)
// get here if the normal Gecko event loop has been awoken above.
// Bug 750713
if (MOZ_LIKELY(AndroidBridge::HasEnv())) {
did_work |= mozilla::widget::android::GeckoAppShell::PumpMessageLoop();
did_work |= mozilla::widget::GeckoAppShell::PumpMessageLoop();
}
#endif

View File

@ -255,7 +255,7 @@ public class GeckoAppShell
// Initialization methods
public static native void registerJavaUiThread();
public static native void nativeInit();
public static native void nativeInit(ClassLoader clsLoader);
// helper methods
public static native void onResume();
@ -339,8 +339,8 @@ public class GeckoAppShell
};
Looper.myQueue().addIdleHandler(idleHandler);
// run gecko -- it will spawn its own thread
GeckoAppShell.nativeInit();
// Initialize AndroidBridge.
nativeInit(GeckoAppShell.class.getClassLoader());
// First argument is the .apk path
String combinedArgs = apkPath + " -greomni " + apkPath;

View File

@ -77,7 +77,7 @@ nsAndroidHistory::RegisterVisitedCallback(nsIURI *aURI, Link *aContent)
list->AppendElement(aContent);
if (AndroidBridge::HasEnv()) {
mozilla::widget::android::GeckoAppShell::CheckURIVisited(uriString);
widget::GeckoAppShell::CheckURIVisited(uriString);
}
return NS_OK;
@ -203,7 +203,7 @@ nsAndroidHistory::SaveVisitURI(nsIURI* aURI) {
// Save this URI in our history
nsAutoCString spec;
(void)aURI->GetSpec(spec);
mozilla::widget::android::GeckoAppShell::MarkURIVisited(NS_ConvertUTF8toUTF16(spec));
widget::GeckoAppShell::MarkURIVisited(NS_ConvertUTF8toUTF16(spec));
}
// Finally, notify that we've been visited.
@ -288,7 +288,7 @@ nsAndroidHistory::SetURITitle(nsIURI *aURI, const nsAString& aTitle)
nsresult rv = aURI->GetSpec(uri);
if (NS_FAILED(rv)) return rv;
NS_ConvertUTF8toUTF16 uriString(uri);
mozilla::widget::android::GeckoAppShell::SetURITitle(uriString, aTitle);
widget::GeckoAppShell::SetURITitle(uriString, aTitle);
}
return NS_OK;
}

View File

@ -8,7 +8,7 @@
#include "AndroidBridge.h"
using namespace mozilla::widget::android;
using namespace mozilla;
NS_IMPL_ISUPPORTS(nsShellService, nsIShellService)
@ -25,6 +25,6 @@ nsShellService::CreateShortcut(const nsAString& aTitle, const nsAString& aURI,
if (!aTitle.Length() || !aURI.Length() || !aIconData.Length())
return NS_ERROR_FAILURE;
mozilla::widget::android::GeckoAppShell::CreateShortcut(aTitle, aURI, aIconData);
widget::GeckoAppShell::CreateShortcut(aTitle, aURI, aIconData);
return NS_OK;
}

View File

@ -77,16 +77,16 @@ Java_org_mozilla_gecko_GeckoAppShell_registerJavaUiThread(JNIEnv * arg0, jclass
#ifdef JNI_STUBS
typedef void (*Java_org_mozilla_gecko_GeckoAppShell_nativeInit_t)(JNIEnv *, jclass);
typedef void (*Java_org_mozilla_gecko_GeckoAppShell_nativeInit_t)(JNIEnv *, jclass, jobject);
static Java_org_mozilla_gecko_GeckoAppShell_nativeInit_t f_Java_org_mozilla_gecko_GeckoAppShell_nativeInit;
extern "C" NS_EXPORT void JNICALL
Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv * arg0, jclass arg1) {
Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv * arg0, jclass arg1, jobject arg2) {
if (!f_Java_org_mozilla_gecko_GeckoAppShell_nativeInit) {
arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
"JNI Function called before it was loaded");
return ;
}
f_Java_org_mozilla_gecko_GeckoAppShell_nativeInit(arg0, arg1);
f_Java_org_mozilla_gecko_GeckoAppShell_nativeInit(arg0, arg1, arg2);
}
#endif

View File

@ -81,7 +81,7 @@ Tickler::Init()
MOZ_ASSERT(!mFD);
if (AndroidBridge::HasEnv()) {
mozilla::widget::android::GeckoAppShell::EnableNetworkNotifications();
widget::GeckoAppShell::EnableNetworkNotifications();
}
mFD = PR_OpenUDPSocket(PR_AF_INET);

View File

@ -90,7 +90,7 @@ bool CameraStreamImpl::Init(const nsCString& contentType, const uint32_t& camera
}
void CameraStreamImpl::Close() {
mozilla::widget::android::GeckoAppShell::CloseCamera();
mozilla::widget::GeckoAppShell::CloseCamera();
mCallback = nullptr;
}

View File

@ -10,8 +10,6 @@
#include "AndroidBridge.h"
using namespace mozilla::widget::android;
NS_IMPL_ISUPPORTS(nsAndroidNetworkLinkService,
nsINetworkLinkService)
@ -33,7 +31,7 @@ nsAndroidNetworkLinkService::GetIsLinkUp(bool *aIsUp)
return NS_OK;
}
*aIsUp = mozilla::widget::android::GeckoAppShell::IsNetworkLinkUp();
*aIsUp = mozilla::widget::GeckoAppShell::IsNetworkLinkUp();
return NS_OK;
}
@ -42,7 +40,7 @@ nsAndroidNetworkLinkService::GetLinkStatusKnown(bool *aIsKnown)
{
NS_ENSURE_TRUE(mozilla::AndroidBridge::Bridge(), NS_ERROR_NOT_IMPLEMENTED);
*aIsKnown = mozilla::widget::android::GeckoAppShell::IsNetworkLinkKnown();
*aIsKnown = mozilla::widget::GeckoAppShell::IsNetworkLinkKnown();
return NS_OK;
}
@ -58,6 +56,6 @@ nsAndroidNetworkLinkService::GetLinkType(uint32_t *aLinkType)
return NS_OK;
}
*aLinkType = mozilla::widget::android::GeckoAppShell::NetworkLinkType();
*aLinkType = mozilla::widget::GeckoAppShell::NetworkLinkType();
return NS_OK;
}

View File

@ -11,7 +11,6 @@
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
using namespace mozilla::widget::android;
#else
#include "nsXPCOM.h"
@ -136,7 +135,7 @@ NS_IMETHODIMP nsAlertsService::CloseAlert(const nsAString& aAlertName,
}
#ifdef MOZ_WIDGET_ANDROID
mozilla::widget::android::GeckoAppShell::CloseNotification(aAlertName);
widget::GeckoAppShell::CloseNotification(aAlertName);
return NS_OK;
#else
@ -157,9 +156,9 @@ NS_IMETHODIMP nsAlertsService::OnProgress(const nsAString & aAlertName,
const nsAString & aAlertText)
{
#ifdef MOZ_WIDGET_ANDROID
mozilla::widget::android::GeckoAppShell::AlertsProgressListener_OnProgress(aAlertName,
aProgress, aProgressMax,
aAlertText);
widget::GeckoAppShell::AlertsProgressListener_OnProgress(aAlertName,
aProgress, aProgressMax,
aAlertText);
return NS_OK;
#else
return NS_ERROR_NOT_IMPLEMENTED;
@ -169,7 +168,7 @@ NS_IMETHODIMP nsAlertsService::OnProgress(const nsAString & aAlertName,
NS_IMETHODIMP nsAlertsService::OnCancel(const nsAString & aAlertName)
{
#ifdef MOZ_WIDGET_ANDROID
mozilla::widget::android::GeckoAppShell::CloseNotification(aAlertName);
widget::GeckoAppShell::CloseNotification(aAlertName);
return NS_OK;
#else
return NS_ERROR_NOT_IMPLEMENTED;

View File

@ -57,7 +57,6 @@
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
using namespace mozilla::widget::android;
#endif
#ifdef MOZ_WIDGET_GTK
@ -2787,7 +2786,7 @@ nsDownload::SetState(DownloadState aState)
if (mimeInfo)
mimeInfo->GetMIMEType(contentType);
mozilla::widget::android::DownloadsIntegration::ScanMedia(path, NS_ConvertUTF8toUTF16(contentType));
mozilla::widget::DownloadsIntegration::ScanMedia(path, NS_ConvertUTF8toUTF16(contentType));
}
#else
if (addToRecentDocs && !mPrivate) {

View File

@ -84,7 +84,7 @@ nsresult DownloadPlatform::DownloadDone(nsIURI* aSource, nsIFile* aTarget,
bool addToRecentDocs = Preferences::GetBool(PREF_BDM_ADDTORECENTDOCS);
#ifdef MOZ_WIDGET_ANDROID
if (addToRecentDocs) {
mozilla::widget::android::DownloadsIntegration::ScanMedia(path, NS_ConvertUTF8toUTF16(aContentType));
mozilla::widget::DownloadsIntegration::ScanMedia(path, NS_ConvertUTF8toUTF16(aContentType));
}
#else
if (addToRecentDocs && !aIsPrivate) {

View File

@ -14,7 +14,7 @@ nsParentalControlsService::nsParentalControlsService() :
mEnabled(false)
{
if (mozilla::AndroidBridge::HasEnv()) {
mEnabled = mozilla::widget::android::RestrictedProfiles::IsUserRestricted();
mEnabled = mozilla::widget::RestrictedProfiles::IsUserRestricted();
}
}
@ -90,7 +90,7 @@ nsParentalControlsService::IsAllowed(int16_t aAction,
NS_ENSURE_SUCCESS(rv, rv);
}
*_retval = mozilla::widget::android::RestrictedProfiles::IsAllowed(aAction,
*_retval = mozilla::widget::RestrictedProfiles::IsAllowed(aAction,
NS_ConvertUTF8toUTF16(url));
return rv;
}

View File

@ -75,7 +75,7 @@ GeckoStart(void *data, const nsXREAppData *appData)
if (result)
LOG("XRE_main returned %d", result);
mozilla::widget::android::GeckoAppShell::NotifyXreExit();
mozilla::widget::GeckoAppShell::NotifyXreExit();
free(targs[0]);
nsMemory::Free(data);

View File

@ -1701,7 +1701,7 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative,
SaveToEnv("MOZ_LAUNCHED_CHILD=1");
#if defined(MOZ_WIDGET_ANDROID)
mozilla::widget::android::GeckoAppShell::ScheduleRestart();
mozilla::widget::GeckoAppShell::ScheduleRestart();
#else
#if defined(XP_MACOSX)
CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
@ -1839,7 +1839,7 @@ ProfileLockedDialog(nsIFile* aProfileDir, nsIFile* aProfileLocalDir,
if (aUnlocker) {
int32_t button;
#ifdef MOZ_WIDGET_ANDROID
mozilla::widget::android::GeckoAppShell::KillAnyZombies();
mozilla::widget::GeckoAppShell::KillAnyZombies();
button = 0;
#else
const uint32_t flags =
@ -1868,7 +1868,7 @@ ProfileLockedDialog(nsIFile* aProfileDir, nsIFile* aProfileLocalDir,
}
} else {
#ifdef MOZ_WIDGET_ANDROID
if (mozilla::widget::android::GeckoAppShell::UnlockProfile()) {
if (mozilla::widget::GeckoAppShell::UnlockProfile()) {
return NS_LockProfilePath(aProfileDir, aProfileLocalDir,
nullptr, aResult);
}

View File

@ -273,7 +273,7 @@ void BuildJavaThreadJSObject(JSStreamWriter& b)
firstRun = false;
double sampleTime =
mozilla::widget::android::GeckoJavaSampler::GetSampleTimeJavaProfiling(0, sampleId);
mozilla::widget::GeckoJavaSampler::GetSampleTimeJavaProfiling(0, sampleId);
b.BeginObject();
b.NameValue("time", sampleTime);
@ -350,11 +350,11 @@ void TableTicker::StreamJSObject(JSStreamWriter& b)
#if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
if (ProfileJava()) {
mozilla::widget::android::GeckoJavaSampler::PauseJavaProfiling();
mozilla::widget::GeckoJavaSampler::PauseJavaProfiling();
BuildJavaThreadJSObject(b);
mozilla::widget::android::GeckoJavaSampler::UnpauseJavaProfiling();
mozilla::widget::GeckoJavaSampler::UnpauseJavaProfiling();
}
#endif

View File

@ -27,7 +27,6 @@
#if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
#include "AndroidBridge.h"
using namespace mozilla::widget::android;
#endif
mozilla::ThreadLocal<PseudoStack *> tlsPseudoStack;
@ -789,7 +788,7 @@ void mozilla_sampler_start(int aProfileEntries, double aInterval,
if (javaInterval < 10) {
aInterval = 10;
}
mozilla::widget::android::GeckoJavaSampler::StartJavaProfiling(javaInterval, 1000);
mozilla::widget::GeckoJavaSampler::StartJavaProfiling(javaInterval, 1000);
}
#endif

View File

@ -6,7 +6,7 @@
#include "nsAndroidHandlerApp.h"
#include "AndroidBridge.h"
using namespace mozilla::widget::android;
using namespace mozilla;
NS_IMPL_ISUPPORTS(nsAndroidHandlerApp, nsIHandlerApp, nsISharingHandlerApp)
@ -76,15 +76,16 @@ nsAndroidHandlerApp::LaunchWithURI(nsIURI *aURI, nsIInterfaceRequestor *aWindowC
{
nsCString uriSpec;
aURI->GetSpec(uriSpec);
return mozilla::widget::android::GeckoAppShell::OpenUriExternal
(NS_ConvertUTF8toUTF16(uriSpec), NS_ConvertUTF8toUTF16(mMimeType), mPackageName, mClassName, mAction) ?
NS_OK : NS_ERROR_FAILURE;
return widget::GeckoAppShell::OpenUriExternal(
uriSpec, mMimeType, mPackageName, mClassName,
mAction, EmptyString()) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsAndroidHandlerApp::Share(const nsAString & data, const nsAString & title)
{
return mozilla::widget::android::GeckoAppShell::OpenUriExternal(data, NS_ConvertUTF8toUTF16(mMimeType),
mPackageName, mClassName, mAction) ? NS_OK : NS_ERROR_FAILURE;
return widget::GeckoAppShell::OpenUriExternal(
data, mMimeType, mPackageName, mClassName,
mAction, EmptyString()) ? NS_OK : NS_ERROR_FAILURE;
}

View File

@ -31,8 +31,8 @@ nsExternalSharingAppService::ShareWithDefault(const nsAString & data,
{
NS_NAMED_LITERAL_STRING(sendAction, "android.intent.action.SEND");
const nsString emptyString = EmptyString();
return mozilla::widget::android::GeckoAppShell::OpenUriExternal(data,
mime, emptyString,emptyString, sendAction, title) ? NS_OK : NS_ERROR_FAILURE;
return widget::GeckoAppShell::OpenUriExternal(data,
mime, emptyString, emptyString, sendAction, title) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP

View File

@ -10,7 +10,7 @@
#include "nsStringEnumerator.h"
#include "nsNetUtil.h"
using namespace mozilla::widget::android;
using namespace mozilla;
NS_IMPL_ISUPPORTS(nsMIMEInfoAndroid, nsIMIMEInfo, nsIHandlerInfo)
@ -36,7 +36,9 @@ nsMIMEInfoAndroid::LoadUriInternal(nsIURI * aURI)
mimeType = NS_ConvertUTF8toUTF16(mType);
}
if (GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), mimeType)) {
if (widget::GeckoAppShell::OpenUriExternal(
NS_ConvertUTF8toUTF16(uriSpec), mimeType, EmptyString(),
EmptyString(), EmptyString(), EmptyString())) {
return NS_OK;
}
return NS_ERROR_FAILURE;

View File

@ -27,11 +27,11 @@ namespace android {
StaticRefPtr<APZCCallbackHandler> APZCCallbackHandler::sInstance;
NativePanZoomController*
APZCCallbackHandler::SetNativePanZoomController(jobject obj)
NativePanZoomController::LocalRef
APZCCallbackHandler::SetNativePanZoomController(NativePanZoomController::Param obj)
{
NativePanZoomController* old = mNativePanZoomController;
mNativePanZoomController = NativePanZoomController::Wrap(obj);
NativePanZoomController::LocalRef old = mNativePanZoomController;
mNativePanZoomController = obj;
return old;
}

View File

@ -7,6 +7,7 @@
#define APZCCallbackHandler_h__
#include "mozilla/layers/GeckoContentController.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/TimeStamp.h"
#include "GeneratedJNIWrappers.h"
#include "nsIDOMWindowUtils.h"
@ -20,7 +21,7 @@ class APZCCallbackHandler MOZ_FINAL : public mozilla::layers::GeckoContentContro
{
private:
static StaticRefPtr<APZCCallbackHandler> sInstance;
NativePanZoomController* mNativePanZoomController;
NativePanZoomController::GlobalRef mNativePanZoomController;
private:
APZCCallbackHandler()
@ -37,7 +38,7 @@ public:
return sInstance.get();
}
NativePanZoomController* SetNativePanZoomController(jobject obj);
NativePanZoomController::LocalRef SetNativePanZoomController(NativePanZoomController::Param obj);
void NotifyDefaultPrevented(uint64_t aInputBlockId, bool aDefaultPrevented);
public: // GeckoContentController methods

View File

@ -46,8 +46,9 @@
#include "SurfaceTexture.h"
using namespace mozilla;
using namespace mozilla::widget::android;
using namespace mozilla::gfx;
using namespace mozilla::jni;
using namespace mozilla::widget;
AndroidBridge* AndroidBridge::sBridge;
pthread_t AndroidBridge::sJavaUiThread = -1;
@ -66,22 +67,29 @@ static android::sp<AndroidRefable> (*android_SurfaceTexture_getNativeWindow)(JNI
jclass AndroidBridge::GetClassGlobalRef(JNIEnv* env, const char* className)
{
jobject classLocalRef = env->FindClass(className);
if (!classLocalRef) {
ALOG(">>> FATAL JNI ERROR! FindClass(className=\"%s\") failed. Did ProGuard optimize away something it shouldn't have?",
// First try the default class loader.
auto classRef = ClassObject::LocalRef::Adopt(
env, env->FindClass(className));
if (!classRef && sBridge && sBridge->mClassLoader) {
// If the default class loader failed but we have an app class loader, try that.
// Clear the pending exception from failed FindClass call above.
env->ExceptionClear();
classRef = ClassObject::LocalRef::Adopt(env,
env->CallObjectMethod(sBridge->mClassLoader.Get(),
sBridge->mClassLoaderLoadClass,
Param<String>::Type(className, env).Get()));
}
if (!classRef) {
ALOG(">>> FATAL JNI ERROR! FindClass(className=\"%s\") failed. "
"Did ProGuard optimize away something it shouldn't have?",
className);
env->ExceptionDescribe();
MOZ_CRASH();
}
jobject classGlobalRef = env->NewGlobalRef(classLocalRef);
if (!classGlobalRef) {
env->ExceptionDescribe();
MOZ_CRASH();
}
// Local ref no longer necessary because we have a global ref.
env->DeleteLocalRef(classLocalRef);
classLocalRef = nullptr;
return static_cast<jclass>(classGlobalRef);
return ClassObject::GlobalRef(env, classRef).Forget();
}
jmethodID AndroidBridge::GetMethodID(JNIEnv* env, jclass jClass,
@ -141,7 +149,7 @@ jfieldID AndroidBridge::GetStaticFieldID(JNIEnv* env, jclass jClass,
}
void
AndroidBridge::ConstructBridge(JNIEnv *jEnv)
AndroidBridge::ConstructBridge(JNIEnv *jEnv, Object::Param clsLoader)
{
/* NSS hack -- bionic doesn't handle recursive unloads correctly,
* because library finalizer functions are called with the dynamic
@ -154,14 +162,14 @@ AndroidBridge::ConstructBridge(JNIEnv *jEnv)
PR_NewThreadPrivateIndex(&sJavaEnvThreadIndex, JavaThreadDetachFunc);
AndroidBridge *bridge = new AndroidBridge();
if (!bridge->Init(jEnv)) {
if (!bridge->Init(jEnv, clsLoader)) {
delete bridge;
}
sBridge = bridge;
}
bool
AndroidBridge::Init(JNIEnv *jEnv)
AndroidBridge::Init(JNIEnv *jEnv, Object::Param clsLoader)
{
ALOG_BRIDGE("AndroidBridge::Init");
jEnv->GetJavaVM(&mJavaVM);
@ -171,6 +179,11 @@ AndroidBridge::Init(JNIEnv *jEnv)
AutoLocalJNIFrame jniFrame(jEnv);
mClassLoader = Object::GlobalRef(jEnv, clsLoader);
mClassLoaderLoadClass = GetMethodID(
jEnv, jEnv->GetObjectClass(clsLoader.Get()),
"loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
mJNIEnv = nullptr;
mThread = -1;
mGLControllerObj = nullptr;
@ -228,14 +241,6 @@ AndroidBridge::Init(JNIEnv *jEnv)
InitAndroidJavaWrappers(jEnv);
if (mAPIVersion >= 16 /* Jelly Bean */) {
sdk::InitMediaCodecStubs(jEnv);
}
if (mAPIVersion >= 14 /* ICS */) {
sdk::InitSurfaceTextureStubs(jEnv);
}
// jEnv should NOT be cached here by anything -- the jEnv here
// is not valid for the real gecko main thread, which is set
// at SetMainThread time.
@ -434,20 +439,17 @@ AndroidBridge::GetHandlersForMimeType(const nsAString& aMimeType,
{
ALOG_BRIDGE("AndroidBridge::GetHandlersForMimeType");
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jobjectArray arr =
mozilla::widget::android::GeckoAppShell::GetHandlersForMimeTypeWrapper(aMimeType, aAction);
auto arr = GeckoAppShell::GetHandlersForMimeTypeWrapper(aMimeType, aAction);
if (!arr)
return false;
jsize len = env->GetArrayLength(arr);
JNIEnv* const env = arr.Env();
jsize len = env->GetArrayLength(arr.Get());
if (!aHandlersArray)
return len > 0;
getHandlersFromStringArray(env, arr, len, aHandlersArray,
getHandlersFromStringArray(env, arr.Get(), len, aHandlersArray,
aDefaultApp, aAction,
NS_ConvertUTF16toUTF8(aMimeType));
return true;
@ -461,19 +463,17 @@ AndroidBridge::GetHandlersForURL(const nsAString& aURL,
{
ALOG_BRIDGE("AndroidBridge::GetHandlersForURL");
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jobjectArray arr = mozilla::widget::android::GeckoAppShell::GetHandlersForURLWrapper(aURL, aAction);
auto arr = GeckoAppShell::GetHandlersForURLWrapper(aURL, aAction);
if (!arr)
return false;
jsize len = env->GetArrayLength(arr);
JNIEnv* const env = arr.Env();
jsize len = env->GetArrayLength(arr.Get());
if (!aHandlersArray)
return len > 0;
getHandlersFromStringArray(env, arr, len, aHandlersArray,
getHandlersFromStringArray(env, arr.Get(), len, aHandlersArray,
aDefaultApp, aAction);
return true;
}
@ -483,16 +483,11 @@ AndroidBridge::GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString&
{
ALOG_BRIDGE("AndroidBridge::GetMimeTypeFromExtensions");
JNIEnv *env = GetJNIEnv();
auto jstrType = GeckoAppShell::GetMimeTypeFromExtensionsWrapper(aFileExt);
AutoLocalJNIFrame jniFrame(env, 1);
jstring jstrType = mozilla::widget::android::GeckoAppShell::GetMimeTypeFromExtensionsWrapper
(NS_ConvertUTF8toUTF16(aFileExt));
if (!jstrType) {
return;
if (jstrType) {
aMimeType = jstrType;
}
nsJNIString jniStr(jstrType, env);
CopyUTF16toUTF8(jniStr.get(), aMimeType);
}
void
@ -500,16 +495,11 @@ AndroidBridge::GetExtensionFromMimeType(const nsACString& aMimeType, nsACString&
{
ALOG_BRIDGE("AndroidBridge::GetExtensionFromMimeType");
JNIEnv *env = GetJNIEnv();
auto jstrExt = GeckoAppShell::GetExtensionFromMimeTypeWrapper(aMimeType);
AutoLocalJNIFrame jniFrame(env, 1);
jstring jstrExt = mozilla::widget::android::GeckoAppShell::GetExtensionFromMimeTypeWrapper
(NS_ConvertUTF8toUTF16(aMimeType));
if (!jstrExt) {
return;
if (jstrExt) {
aFileExt = nsCString(jstrExt);
}
nsJNIString jniStr(jstrExt, env);
CopyUTF16toUTF8(jniStr.get(), aFileExt);
}
bool
@ -517,16 +507,12 @@ AndroidBridge::GetClipboardText(nsAString& aText)
{
ALOG_BRIDGE("AndroidBridge::GetClipboardText");
JNIEnv *env = GetJNIEnv();
auto text = Clipboard::GetClipboardTextWrapper();
AutoLocalJNIFrame jniFrame(env, 1);
jstring result = Clipboard::GetClipboardTextWrapper();
if (!result)
return false;
nsJNIString jniStr(result, env);
aText.Assign(jniStr);
return true;
if (text) {
aText = nsString(text);
}
return !!text;
}
void
@ -542,7 +528,7 @@ AndroidBridge::ShowAlertNotification(const nsAString& aImageUrl,
nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeAddObserver(aAlertName, aAlertListener));
}
mozilla::widget::android::GeckoAppShell::ShowAlertNotificationWrapper
GeckoAppShell::ShowAlertNotificationWrapper
(aImageUrl, aAlertTitle, aAlertText, aAlertCookie, aAlertName);
}
@ -555,7 +541,7 @@ AndroidBridge::GetDPI()
const int DEFAULT_DPI = 160;
sDPI = mozilla::widget::android::GeckoAppShell::GetDpiWrapper();
sDPI = GeckoAppShell::GetDpiWrapper();
if (!sDPI) {
return DEFAULT_DPI;
}
@ -575,7 +561,7 @@ AndroidBridge::GetScreenDepth()
const int DEFAULT_DEPTH = 16;
if (HasEnv()) {
sDepth = mozilla::widget::android::GeckoAppShell::GetScreenDepthWrapper();
sDepth = GeckoAppShell::GetScreenDepthWrapper();
}
if (!sDepth)
return DEFAULT_DEPTH;
@ -593,10 +579,6 @@ AndroidBridge::Vibrate(const nsTArray<uint32_t>& aPattern)
return;
}
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
// It's clear if this worth special-casing, but it creates less
// java junk, so dodges the GC.
if (len == 1) {
@ -605,13 +587,16 @@ AndroidBridge::Vibrate(const nsTArray<uint32_t>& aPattern)
ALOG_BRIDGE(" invalid vibration duration < 0");
return;
}
mozilla::widget::android::GeckoAppShell::Vibrate1(d);
GeckoAppShell::Vibrate1(d);
return;
}
// First element of the array vibrate() expects is how long to wait
// *before* vibrating. For us, this is always 0.
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jlongArray array = env->NewLongArray(len + 1);
if (!array) {
ALOG_BRIDGE(" failed to allocate array");
@ -631,7 +616,7 @@ AndroidBridge::Vibrate(const nsTArray<uint32_t>& aPattern)
}
env->ReleaseLongArrayElements(array, elts, 0);
mozilla::widget::android::GeckoAppShell::VibrateA(array, -1/*don't repeat*/);
GeckoAppShell::VibrateA(LongArray::Ref::From(array), -1 /* don't repeat */);
}
void
@ -642,16 +627,13 @@ AndroidBridge::GetSystemColors(AndroidSystemColors *aColors)
if (!aColors)
return;
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jintArray arr = mozilla::widget::android::GeckoAppShell::GetSystemColoursWrapper();
auto arr = GeckoAppShell::GetSystemColoursWrapper();
if (!arr)
return;
uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr));
jint *elements = env->GetIntArrayElements(arr, 0);
JNIEnv* const env = arr.Env();
uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr.Get()));
jint *elements = env->GetIntArrayElements(arr.Get(), 0);
uint32_t colorsCount = sizeof(AndroidSystemColors) / sizeof(nscolor);
if (len < colorsCount)
@ -667,7 +649,7 @@ AndroidBridge::GetSystemColors(AndroidSystemColors *aColors)
colors[i] = (androidColor & 0xff00ff00) | (b << 16) | r;
}
env->ReleaseIntArrayElements(arr, elements, 0);
env->ReleaseIntArrayElements(arr.Get(), elements, 0);
}
void
@ -678,30 +660,27 @@ AndroidBridge::GetIconForExtension(const nsACString& aFileExt, uint32_t aIconSiz
if (!aBuf)
return;
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jbyteArray arr = mozilla::widget::android::GeckoAppShell::GetIconForExtensionWrapper
auto arr = GeckoAppShell::GetIconForExtensionWrapper
(NS_ConvertUTF8toUTF16(aFileExt), aIconSize);
NS_ASSERTION(arr != nullptr, "AndroidBridge::GetIconForExtension: Returned pixels array is null!");
if (!arr)
return;
uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr));
jbyte *elements = env->GetByteArrayElements(arr, 0);
JNIEnv* const env = arr.Env();
uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr.Get()));
jbyte *elements = env->GetByteArrayElements(arr.Get(), 0);
uint32_t bufSize = aIconSize * aIconSize * 4;
NS_ASSERTION(len == bufSize, "AndroidBridge::GetIconForExtension: Pixels array is incomplete!");
if (len == bufSize)
memcpy(aBuf, elements, bufSize);
env->ReleaseByteArrayElements(arr, elements, 0);
env->ReleaseByteArrayElements(arr.Get(), elements, 0);
}
void
AndroidBridge::SetLayerClient(JNIEnv* env, jobject jobj)
AndroidBridge::SetLayerClient(GeckoLayerClient::Param jobj)
{
// if resetting is true, that means Android destroyed our GeckoApp activity
// and we had to recreate it, but all the Gecko-side things were not destroyed.
@ -709,13 +688,7 @@ AndroidBridge::SetLayerClient(JNIEnv* env, jobject jobj)
// we do here.
bool resetting = (mLayerClient != nullptr);
if (resetting) {
// clear out the old layer client
delete mLayerClient;
mLayerClient = nullptr;
}
mLayerClient = mozilla::widget::android::GeckoLayerClient::Wrap(jobj);
mLayerClient = jobj;
if (resetting) {
// since we are re-linking the new java objects to Gecko, we need to get
@ -728,17 +701,13 @@ AndroidBridge::SetLayerClient(JNIEnv* env, jobject jobj)
void
AndroidBridge::RegisterCompositor(JNIEnv *env)
{
if (mGLControllerObj != nullptr && !mGLControllerObj->isNull()) {
if (mGLControllerObj != nullptr) {
// we already have this set up, no need to do it again
return;
}
jobject glController = LayerView::RegisterCompositorWrapper();
if (!glController) {
return;
}
mGLControllerObj = GLController::Wrap(glController);
mGLControllerObj = GLController::LocalRef(
LayerView::RegisterCompositorWrapper());
}
EGLSurface
@ -749,15 +718,14 @@ AndroidBridge::CreateEGLSurfaceForCompositor()
}
MOZ_ASSERT(mGLControllerObj, "AndroidBridge::CreateEGLSurfaceForCompositor called with a null GL controller ref");
JNIEnv* env = GetJNIForThread(); // called on the compositor thread
AutoLocalJNIFrame jniFrame(env, 1);
jobject eglSurface = mGLControllerObj->CreateEGLSurfaceForCompositorWrapper();
if (!eglSurface)
auto eglSurface = mGLControllerObj->CreateEGLSurfaceForCompositorWrapper();
if (!eglSurface) {
return nullptr;
}
EGLSurface ret = reinterpret_cast<EGLSurface>(env->GetIntField(eglSurface, jEGLSurfacePointerField));
return ret;
JNIEnv* const env = GetJNIForThread(); // called on the compositor thread
return reinterpret_cast<EGLSurface>(
env->GetIntField(eglSurface.Get(), jEGLSurfacePointerField));
}
bool
@ -1007,16 +975,14 @@ AndroidBridge::ValidateBitmap(jobject bitmap, int width, int height)
bool
AndroidBridge::InitCamera(const nsCString& contentType, uint32_t camera, uint32_t *width, uint32_t *height, uint32_t *fps)
{
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jintArray arr = mozilla::widget::android::GeckoAppShell::InitCameraWrapper
auto arr = GeckoAppShell::InitCameraWrapper
(NS_ConvertUTF8toUTF16(contentType), (int32_t) camera, (int32_t) *width, (int32_t) *height);
if (!arr)
return false;
jint *elements = env->GetIntArrayElements(arr, 0);
JNIEnv* const env = arr.Env();
jint *elements = env->GetIntArrayElements(arr.Get(), 0);
*width = elements[1];
*height = elements[2];
@ -1024,7 +990,7 @@ AndroidBridge::InitCamera(const nsCString& contentType, uint32_t camera, uint32_
bool res = elements[0] == 1;
env->ReleaseIntArrayElements(arr, elements, 0);
env->ReleaseIntArrayElements(arr.Get(), elements, 0);
return res;
}
@ -1034,24 +1000,22 @@ AndroidBridge::GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInf
{
ALOG_BRIDGE("AndroidBridge::GetCurrentBatteryInformation");
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
// To prevent calling too many methods through JNI, the Java method returns
// an array of double even if we actually want a double and a boolean.
jdoubleArray arr = mozilla::widget::android::GeckoAppShell::GetCurrentBatteryInformationWrapper();
if (!arr || env->GetArrayLength(arr) != 3) {
auto arr = GeckoAppShell::GetCurrentBatteryInformationWrapper();
JNIEnv* const env = arr.Env();
if (!arr || env->GetArrayLength(arr.Get()) != 3) {
return;
}
jdouble* info = env->GetDoubleArrayElements(arr, 0);
jdouble* info = env->GetDoubleArrayElements(arr.Get(), 0);
aBatteryInfo->level() = info[0];
aBatteryInfo->charging() = info[1] == 1.0f;
aBatteryInfo->remainingTime() = info[2];
env->ReleaseDoubleArrayElements(arr, info, 0);
env->ReleaseDoubleArrayElements(arr.Get(), info, 0);
}
void
@ -1060,9 +1024,8 @@ AndroidBridge::HandleGeckoMessage(JSContext* cx, JS::HandleObject object)
ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
JNIEnv* const env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
const jobject message =
mozilla::widget::CreateNativeJSContainer(env, cx, object);
auto message = Object::LocalRef::Adopt(env,
mozilla::widget::CreateNativeJSContainer(env, cx, object));
GeckoAppShell::HandleGeckoMessageWrapper(message);
}
@ -1118,7 +1081,7 @@ AndroidBridge::SendMessage(const nsAString& aNumber,
if (!QueueSmsRequest(aRequest, &requestId))
return;
mozilla::widget::android::GeckoAppShell::SendMessageWrapper(aNumber, aMessage, requestId);
GeckoAppShell::SendMessageWrapper(aNumber, aMessage, requestId);
}
void
@ -1130,7 +1093,7 @@ AndroidBridge::GetMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequest
if (!QueueSmsRequest(aRequest, &requestId))
return;
mozilla::widget::android::GeckoAppShell::GetMessageWrapper(aMessageId, requestId);
GeckoAppShell::GetMessageWrapper(aMessageId, requestId);
}
void
@ -1142,7 +1105,7 @@ AndroidBridge::DeleteMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequ
if (!QueueSmsRequest(aRequest, &requestId))
return;
mozilla::widget::android::GeckoAppShell::DeleteMessageWrapper(aMessageId, requestId);
GeckoAppShell::DeleteMessageWrapper(aMessageId, requestId);
}
void
@ -1173,7 +1136,8 @@ AndroidBridge::CreateMessageList(const dom::mobilemessage::SmsFilterData& aFilte
int64_t startDate = aFilter.hasStartDate() ? aFilter.startDate() : -1;
int64_t endDate = aFilter.hasEndDate() ? aFilter.endDate() : -1;
GeckoAppShell::CreateMessageListWrapper(startDate, endDate,
numbers, aFilter.numbers().Length(),
ObjectArray::Ref::From(numbers),
aFilter.numbers().Length(),
aFilter.delivery(),
aFilter.hasRead(), aFilter.read(),
aFilter.threadId(),
@ -1189,7 +1153,7 @@ AndroidBridge::GetNextMessageInList(int32_t aListId, nsIMobileMessageCallback* a
if (!QueueSmsRequest(aRequest, &requestId))
return;
mozilla::widget::android::GeckoAppShell::GetNextMessageInListWrapper(aListId, requestId);
GeckoAppShell::GetNextMessageInListWrapper(aListId, requestId);
}
bool
@ -1232,25 +1196,23 @@ AndroidBridge::GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInf
{
ALOG_BRIDGE("AndroidBridge::GetCurrentNetworkInformation");
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
// To prevent calling too many methods through JNI, the Java method returns
// an array of double even if we actually want an integer, a boolean, and an integer.
jdoubleArray arr = mozilla::widget::android::GeckoAppShell::GetCurrentNetworkInformationWrapper();
if (!arr || env->GetArrayLength(arr) != 3) {
auto arr = GeckoAppShell::GetCurrentNetworkInformationWrapper();
JNIEnv* const env = arr.Env();
if (!arr || env->GetArrayLength(arr.Get()) != 3) {
return;
}
jdouble* info = env->GetDoubleArrayElements(arr, 0);
jdouble* info = env->GetDoubleArrayElements(arr.Get(), 0);
aNetworkInfo->type() = info[0];
aNetworkInfo->isWifi() = info[1] == 1.0f;
aNetworkInfo->dhcpGateway() = info[2];
env->ReleaseDoubleArrayElements(arr, info, 0);
env->ReleaseDoubleArrayElements(arr.Get(), info, 0);
}
void *
@ -1258,8 +1220,6 @@ AndroidBridge::LockBitmap(jobject bitmap)
{
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 0);
int err;
void *buf;
@ -1276,8 +1236,6 @@ AndroidBridge::UnlockBitmap(jobject bitmap)
{
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 0);
int err;
if ((err = AndroidBitmap_unlockPixels(env, bitmap)) != 0)
@ -1420,37 +1378,37 @@ AndroidBridge::LockWindow(void *window, unsigned char **bits, int *width, int *h
jobject
AndroidBridge::GetGlobalContextRef() {
if (sGlobalContext == nullptr) {
JNIEnv *env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 4);
jobject context = mozilla::widget::android::GeckoAppShell::GetContext();
if (!context) {
ALOG_BRIDGE("%s: Could not GetContext()", __FUNCTION__);
return 0;
}
jclass contextClass = env->FindClass("android/content/Context");
if (!contextClass) {
ALOG_BRIDGE("%s: Could not find Context class.", __FUNCTION__);
return 0;
}
jmethodID mid = env->GetMethodID(contextClass, "getApplicationContext",
"()Landroid/content/Context;");
if (!mid) {
ALOG_BRIDGE("%s: Could not find getApplicationContext.", __FUNCTION__);
return 0;
}
jobject appContext = env->CallObjectMethod(context, mid);
if (!appContext) {
ALOG_BRIDGE("%s: getApplicationContext failed.", __FUNCTION__);
return 0;
}
sGlobalContext = env->NewGlobalRef(appContext);
MOZ_ASSERT(sGlobalContext);
if (sGlobalContext) {
return sGlobalContext;
}
JNIEnv* const env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 4);
auto context = GeckoAppShell::GetContext();
if (!context) {
ALOG_BRIDGE("%s: Could not GetContext()", __FUNCTION__);
return 0;
}
jclass contextClass = env->FindClass("android/content/Context");
if (!contextClass) {
ALOG_BRIDGE("%s: Could not find Context class.", __FUNCTION__);
return 0;
}
jmethodID mid = env->GetMethodID(contextClass, "getApplicationContext",
"()Landroid/content/Context;");
if (!mid) {
ALOG_BRIDGE("%s: Could not find getApplicationContext.", __FUNCTION__);
return 0;
}
jobject appContext = env->CallObjectMethod(context.Get(), mid);
if (!appContext) {
ALOG_BRIDGE("%s: getApplicationContext failed.", __FUNCTION__);
return 0;
}
sGlobalContext = env->NewGlobalRef(appContext);
MOZ_ASSERT(sGlobalContext);
return sGlobalContext;
}
@ -1476,22 +1434,23 @@ AndroidBridge::UnlockWindow(void* window)
void
AndroidBridge::SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect)
{
mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
if (!client)
if (!mLayerClient) {
return;
}
client->SetFirstPaintViewport((float)aOffset.x, (float)aOffset.y, aZoom.scale,
aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
mLayerClient->SetFirstPaintViewport(float(aOffset.x), float(aOffset.y), aZoom.scale,
aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
}
void
AndroidBridge::SetPageRect(const CSSRect& aCssPageRect)
{
mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
if (!client)
if (!mLayerClient) {
return;
}
client->SetPageRect(aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
mLayerClient->SetPageRect(aCssPageRect.x, aCssPageRect.y,
aCssPageRect.XMost(), aCssPageRect.YMost());
}
void
@ -1499,39 +1458,33 @@ AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLay
bool aLayersUpdated, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aScale,
LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
{
mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
if (!client) {
if (!mLayerClient) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
jobject viewTransformJObj = client->SyncViewportInfo(aDisplayPort.x, aDisplayPort.y,
aDisplayPort.width, aDisplayPort.height,
aDisplayResolution.scale, aLayersUpdated);
NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
ViewTransform::LocalRef viewTransform = mLayerClient->SyncViewportInfo(
aDisplayPort.x, aDisplayPort.y,
aDisplayPort.width, aDisplayPort.height,
aDisplayResolution.scale, aLayersUpdated);
if (!viewTransformJObj) {
return;
}
NS_ABORT_IF_FALSE(viewTransform, "No view transform object!");
ViewTransform* viewTransform = ViewTransform::Wrap(viewTransformJObj);
aScrollOffset = ParentLayerPoint(viewTransform->getx(), viewTransform->gety());
aScale.scale = viewTransform->getscale();
aFixedLayerMargins.top = viewTransform->getfixedLayerMarginTop();
aFixedLayerMargins.right = viewTransform->getfixedLayerMarginRight();
aFixedLayerMargins.bottom = viewTransform->getfixedLayerMarginBottom();
aFixedLayerMargins.left = viewTransform->getfixedLayerMarginLeft();
aOffset.x = viewTransform->getoffsetX();
aOffset.y = viewTransform->getoffsetY();
delete viewTransform;
aScrollOffset = ParentLayerPoint(viewTransform->X(), viewTransform->Y());
aScale.scale = viewTransform->Scale();
aFixedLayerMargins.top = viewTransform->FixedLayerMarginTop();
aFixedLayerMargins.right = viewTransform->FixedLayerMarginRight();
aFixedLayerMargins.bottom = viewTransform->FixedLayerMarginBottom();
aFixedLayerMargins.left = viewTransform->FixedLayerMarginLeft();
aOffset.x = viewTransform->OffsetX();
aOffset.y = viewTransform->OffsetY();
}
void AndroidBridge::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
{
mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
if (!client) {
if (!mLayerClient) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
@ -1541,26 +1494,21 @@ void AndroidBridge::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, floa
dpUnrounded += LayerPoint::FromUnknownPoint(aScrollOffset.ToUnknownPoint());
LayerIntRect dp = gfx::RoundedToInt(dpUnrounded);
jobject viewTransformJObj = client->SyncFrameMetrics(aScrollOffset.x, aScrollOffset.y, aZoom,
aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(),
aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution.scale,
aIsFirstPaint);
ViewTransform::LocalRef viewTransform = mLayerClient->SyncFrameMetrics(
aScrollOffset.x, aScrollOffset.y, aZoom,
aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(),
aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution.scale,
aIsFirstPaint);
NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
if (!viewTransformJObj) {
return;
}
ViewTransform* viewTransform = ViewTransform::Wrap(viewTransformJObj);
NS_ABORT_IF_FALSE(viewTransform, "No view transform object!");
aFixedLayerMargins.top = viewTransform->getfixedLayerMarginTop();
aFixedLayerMargins.right = viewTransform->getfixedLayerMarginRight();
aFixedLayerMargins.bottom = viewTransform->getfixedLayerMarginBottom();
aFixedLayerMargins.left = viewTransform->getfixedLayerMarginLeft();
aFixedLayerMargins.top = viewTransform->FixedLayerMarginTop();
aFixedLayerMargins.right = viewTransform->FixedLayerMarginRight();
aFixedLayerMargins.bottom = viewTransform->FixedLayerMarginBottom();
aFixedLayerMargins.left = viewTransform->FixedLayerMarginLeft();
aOffset.x = viewTransform->getoffsetX();
aOffset.y = viewTransform->getoffsetY();
delete viewTransform;
aOffset.x = viewTransform->OffsetX();
aOffset.y = viewTransform->OffsetY();
}
AndroidBridge::AndroidBridge()
@ -1664,7 +1612,7 @@ AndroidBridge::GetScreenOrientation()
{
ALOG_BRIDGE("AndroidBridge::GetScreenOrientation");
int16_t orientation = mozilla::widget::android::GeckoAppShell::GetScreenOrientationWrapper();
int16_t orientation = GeckoAppShell::GetScreenOrientationWrapper();
if (!orientation)
return dom::eScreenOrientation_None;
@ -1688,20 +1636,13 @@ AndroidBridge::GetProxyForURI(const nsACString & aSpec,
if (!HasEnv()) {
return NS_ERROR_FAILURE;
}
JNIEnv* env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jstring jstrRet =
mozilla::widget::android::GeckoAppShell::GetProxyForURIWrapper(NS_ConvertUTF8toUTF16(aSpec),
NS_ConvertUTF8toUTF16(aScheme),
NS_ConvertUTF8toUTF16(aHost),
aPort);
auto jstrRet = GeckoAppShell::GetProxyForURIWrapper(aSpec, aScheme, aHost, aPort);
if (!jstrRet)
return NS_ERROR_FAILURE;
nsJNIString jniStr(jstrRet, env);
CopyUTF16toUTF8(jniStr, aResult);
aResult = nsCString(jstrRet);
return NS_OK;
}
@ -1728,8 +1669,8 @@ AndroidBridge::AddPluginView(jobject view, const LayoutDeviceRect& rect, bool is
return;
CSSRect cssRect = rect / win->GetDefaultScale();
mozilla::widget::android::GeckoAppShell::AddPluginViewWrapper(view, cssRect.x, cssRect.y,
cssRect.width, cssRect.height, isFullScreen);
GeckoAppShell::AddPluginViewWrapper(Object::Ref::From(view), cssRect.x, cssRect.y,
cssRect.width, cssRect.height, isFullScreen);
}
extern "C"
@ -1740,18 +1681,12 @@ Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *env, jclass, j
bool
AndroidBridge::GetThreadNameJavaProfiling(uint32_t aThreadId, nsCString & aResult)
{
JNIEnv* env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 1);
jstring jstrThreadName =
mozilla::widget::android::GeckoJavaSampler::GetThreadNameJavaProfilingWrapper(aThreadId);
auto jstrThreadName = GeckoJavaSampler::GetThreadNameJavaProfilingWrapper(aThreadId);
if (!jstrThreadName)
return false;
nsJNIString jniStr(jstrThreadName, env);
CopyUTF16toUTF8(jniStr.get(), aResult);
aResult = nsCString(jstrThreadName);
return true;
}
@ -1759,22 +1694,17 @@ bool
AndroidBridge::GetFrameNameJavaProfiling(uint32_t aThreadId, uint32_t aSampleId,
uint32_t aFrameId, nsCString & aResult)
{
JNIEnv* env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 1);
jstring jstrSampleName = mozilla::widget::android::GeckoJavaSampler::GetFrameNameJavaProfilingWrapper
(aThreadId, aSampleId, aFrameId);
auto jstrSampleName = GeckoJavaSampler::GetFrameNameJavaProfilingWrapper
(aThreadId, aSampleId, aFrameId);
if (!jstrSampleName)
return false;
nsJNIString jniStr(jstrSampleName, env);
CopyUTF16toUTF8(jniStr.get(), aResult);
aResult = nsCString(jstrSampleName);
return true;
}
nsresult AndroidBridge::CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, jobject buffer, bool &shouldStore)
nsresult AndroidBridge::CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, Object::Param buffer, bool &shouldStore)
{
nsresult rv;
float scale = 1.0;
@ -1848,7 +1778,7 @@ nsresult AndroidBridge::CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int
bool is24bit = (GetScreenDepth() == 24);
uint32_t stride = bufW * (is24bit ? 4 : 2);
uint8_t* data = static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
uint8_t* data = static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer.Get()));
if (!data)
return NS_ERROR_FAILURE;
@ -1882,13 +1812,13 @@ AndroidBridge::GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDispla
{
ALOG_BRIDGE("Enter: %s", __PRETTY_FUNCTION__);
JNIEnv* env = GetJNIEnv();
if (!mLayerClient || mLayerClient->isNull()) {
if (!mLayerClient) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
AutoLocalJNIFrame jniFrame(env, 0);
JNIEnv* const env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
float x, y, width, height,
pageLeft, pageTop, pageRight, pageBottom,
@ -1908,34 +1838,26 @@ AndroidBridge::GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDispla
metrics->GetCssPageBottom(&cssPageBottom);
metrics->GetZoom(&zoom);
ImmutableViewportMetrics jmetrics = ImmutableViewportMetrics(pageLeft, pageTop, pageRight, pageBottom,
cssPageLeft, cssPageTop, cssPageRight, cssPageBottom,
x, y, x + width, y + height,
zoom);
auto jmetrics = ImmutableViewportMetrics::New(
pageLeft, pageTop, pageRight, pageBottom,
cssPageLeft, cssPageTop, cssPageRight, cssPageBottom,
x, y, x + width, y + height,
zoom);
jobject jobj = mLayerClient->GetDisplayPort(aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, jmetrics.wrappedObject());
if (!jobj) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
DisplayPortMetrics* displayPortMetrics = DisplayPortMetrics::Wrap(jobj);
DisplayPortMetrics::LocalRef displayPortMetrics = mLayerClient->GetDisplayPort(
aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, jmetrics);
AndroidRectF rect(env, displayPortMetrics->getMPosition());
if (jniFrame.CheckForException()) {
if (!displayPortMetrics) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
float resolution = displayPortMetrics->getResolution();
if (jniFrame.CheckForException()) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
AndroidRectF rect(env, displayPortMetrics->MPosition().Get());
float resolution = displayPortMetrics->Resolution();
*displayPort = new nsAndroidDisplayport(rect, resolution);
(*displayPort)->AddRef();
delete displayPortMetrics;
ALOG_BRIDGE("Exit: %s", __PRETTY_FUNCTION__);
}
@ -1958,35 +1880,30 @@ AndroidBridge::IsContentDocumentDisplayed()
}
bool
AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution,
bool aDrawingCritical, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aZoom)
AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
const LayerRect& aDisplayPort, float aDisplayResolution,
bool aDrawingCritical, ParentLayerPoint& aScrollOffset,
CSSToParentLayerScale& aZoom)
{
mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
if (!client) {
if (!mLayerClient) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return false;
}
jobject progressiveUpdateDataJObj = client->ProgressiveUpdateCallback(aHasPendingNewThebesContent,
(float)aDisplayPort.x,
(float)aDisplayPort.y,
(float)aDisplayPort.width,
(float)aDisplayPort.height,
aDisplayResolution,
!aDrawingCritical);
ProgressiveUpdateData::LocalRef progressiveUpdateData =
mLayerClient->ProgressiveUpdateCallback(aHasPendingNewThebesContent,
(float)aDisplayPort.x,
(float)aDisplayPort.y,
(float)aDisplayPort.width,
(float)aDisplayPort.height,
aDisplayResolution,
!aDrawingCritical);
NS_ABORT_IF_FALSE(progressiveUpdateDataJObj, "No progressive update data!");
aScrollOffset.x = progressiveUpdateData->X();
aScrollOffset.y = progressiveUpdateData->Y();
aZoom.scale = progressiveUpdateData->Scale();
ProgressiveUpdateData* progressiveUpdateData = ProgressiveUpdateData::Wrap(progressiveUpdateDataJObj);
aScrollOffset.x = progressiveUpdateData->getx();
aScrollOffset.y = progressiveUpdateData->gety();
aZoom.scale = progressiveUpdateData->getscale();
bool ret = progressiveUpdateData->getabort();
delete progressiveUpdateData;
return ret;
return progressiveUpdateData->Abort();
}
void
@ -2040,30 +1957,31 @@ AndroidBridge::RunDelayedUiThreadTasks()
return -1;
}
jobject AndroidBridge::ChannelCreate(jobject stream) {
JNIEnv *env = GetJNIForThread();
env->PushLocalFrame(1);
jobject channel = env->CallStaticObjectMethod(sBridge->jReadableByteChannel, sBridge->jChannelCreate, stream);
return env->PopLocalFrame(channel);
Object::LocalRef AndroidBridge::ChannelCreate(Object::Param stream) {
JNIEnv* const env = GetJNIForThread();
auto rv = Object::LocalRef::Adopt(env, env->CallStaticObjectMethod(
sBridge->jReadableByteChannel, sBridge->jChannelCreate, stream.Get()));
HandleUncaughtException(env);
return rv;
}
void AndroidBridge::InputStreamClose(jobject obj) {
JNIEnv *env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 1);
env->CallVoidMethod(obj, sBridge->jClose);
void AndroidBridge::InputStreamClose(Object::Param obj) {
JNIEnv* const env = GetJNIForThread();
env->CallVoidMethod(obj.Get(), sBridge->jClose);
HandleUncaughtException(env);
}
uint32_t AndroidBridge::InputStreamAvailable(jobject obj) {
JNIEnv *env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 1);
return env->CallIntMethod(obj, sBridge->jAvailable);
uint32_t AndroidBridge::InputStreamAvailable(Object::Param obj) {
JNIEnv* const env = GetJNIForThread();
auto rv = env->CallIntMethod(obj.Get(), sBridge->jAvailable);
HandleUncaughtException(env);
return rv;
}
nsresult AndroidBridge::InputStreamRead(jobject obj, char *aBuf, uint32_t aCount, uint32_t *aRead) {
JNIEnv *env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 1);
jobject arr = env->NewDirectByteBuffer(aBuf, aCount);
jint read = env->CallIntMethod(obj, sBridge->jByteBufferRead, arr);
nsresult AndroidBridge::InputStreamRead(Object::Param obj, char *aBuf, uint32_t aCount, uint32_t *aRead) {
JNIEnv* const env = GetJNIForThread();
auto arr = Object::LocalRef::Adopt(env, env->NewDirectByteBuffer(aBuf, aCount));
jint read = env->CallIntMethod(obj.Get(), sBridge->jByteBufferRead, arr.Get());
if (env->ExceptionCheck()) {
env->ExceptionClear();
@ -2079,12 +1997,10 @@ nsresult AndroidBridge::InputStreamRead(jobject obj, char *aBuf, uint32_t aCount
}
nsresult AndroidBridge::GetExternalPublicDirectory(const nsAString& aType, nsAString& aPath) {
AutoLocalJNIFrame frame(1);
const jstring path = GeckoAppShell::GetExternalPublicDirectory(aType);
auto path = GeckoAppShell::GetExternalPublicDirectory(aType);
if (!path) {
return NS_ERROR_NOT_AVAILABLE;
}
nsJNIString pathStr(path, frame.GetEnv());
aPath.Assign(pathStr);
aPath = nsString(path);
return NS_OK;
}

View File

@ -15,6 +15,7 @@
#include "nsCOMArray.h"
#include "GeneratedJNIWrappers.h"
#include "AndroidJavaWrappers.h"
#include "nsIMutableArray.h"
#include "nsIMIMEInfo.h"
@ -137,7 +138,7 @@ public:
return pthread_equal(pthread_self(), sJavaUiThread);
}
static void ConstructBridge(JNIEnv *jEnv);
static void ConstructBridge(JNIEnv *jEnv, jni::Object::Param clsLoader);
static AndroidBridge *Bridge() {
return sBridge;
@ -187,7 +188,7 @@ public:
bool GetThreadNameJavaProfiling(uint32_t aThreadId, nsCString & aResult);
bool GetFrameNameJavaProfiling(uint32_t aThreadId, uint32_t aSampleId, uint32_t aFrameId, nsCString & aResult);
nsresult CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, jobject buffer, bool &shouldStore);
nsresult CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, jni::Object::Param buffer, bool &shouldStore);
void GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort);
void ContentDocumentChanged();
bool IsContentDocumentDisplayed();
@ -195,8 +196,8 @@ public:
bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical,
mozilla::ParentLayerPoint& aScrollOffset, mozilla::CSSToParentLayerScale& aZoom);
void SetLayerClient(JNIEnv* env, jobject jobj);
mozilla::widget::android::GeckoLayerClient* GetLayerClient() { return mLayerClient; }
void SetLayerClient(widget::GeckoLayerClient::Param jobj);
const widget::GeckoLayerClient::Ref& GetLayerClient() { return mLayerClient; }
bool GetHandlersForURL(const nsAString& aURL,
nsIMutableArray* handlersArray = nullptr,
@ -333,11 +334,11 @@ public:
static jmethodID GetMethodID(JNIEnv* env, jclass jClass, const char* methodName, const char* methodType);
static jmethodID GetStaticMethodID(JNIEnv* env, jclass jClass, const char* methodName, const char* methodType);
static jobject ChannelCreate(jobject);
static jni::Object::LocalRef ChannelCreate(jni::Object::Param);
static void InputStreamClose(jobject obj);
static uint32_t InputStreamAvailable(jobject obj);
static nsresult InputStreamRead(jobject obj, char *aBuf, uint32_t aCount, uint32_t *aRead);
static void InputStreamClose(jni::Object::Param obj);
static uint32_t InputStreamAvailable(jni::Object::Param obj);
static nsresult InputStreamRead(jni::Object::Param obj, char *aBuf, uint32_t aCount, uint32_t *aRead);
static nsresult GetExternalPublicDirectory(const nsAString& aType, nsAString& aPath);
@ -353,7 +354,7 @@ protected:
JNIEnv *mJNIEnv;
pthread_t mThread;
mozilla::widget::android::GeckoLayerClient *mLayerClient;
widget::GeckoLayerClient::GlobalRef mLayerClient;
// the android.telephony.SmsMessage class
jclass mAndroidSmsMessageClass;
@ -362,7 +363,7 @@ protected:
~AndroidBridge();
void InitStubs(JNIEnv *jEnv);
bool Init(JNIEnv *jEnv);
bool Init(JNIEnv *jEnv, jni::Object::Param clsLoader);
bool mOpenedGraphicsLibraries;
void OpenGraphicsLibraries();
@ -404,11 +405,14 @@ protected:
jclass jLayerView;
jfieldID jEGLSurfacePointerField;
mozilla::widget::android::GLController *mGLControllerObj;
widget::GLController::GlobalRef mGLControllerObj;
// some convinient types to have around
jclass jStringClass;
jni::Object::GlobalRef mClassLoader;
jmethodID mClassLoaderLoadClass;
// calls we've dlopened from libjnigraphics.so
int (* AndroidBitmap_getInfo)(JNIEnv *env, jobject bitmap, void *info);
int (* AndroidBitmap_lockPixels)(JNIEnv *env, jobject bitmap, void **buffer);

View File

@ -48,6 +48,7 @@ using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::dom::mobilemessage;
using namespace mozilla::layers;
using namespace mozilla::widget;
using namespace mozilla::widget::android;
/* Forward declare all the JNI methods as extern "C" */
@ -64,9 +65,9 @@ Java_org_mozilla_gecko_GeckoAppShell_registerJavaUiThread(JNIEnv *jenv, jclass j
}
NS_EXPORT void JNICALL
Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv *jenv, jclass jc)
Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv *jenv, jclass, jobject clsLoader)
{
AndroidBridge::ConstructBridge(jenv);
AndroidBridge::ConstructBridge(jenv, jni::Object::Ref::From(clsLoader));
}
NS_EXPORT void JNICALL
@ -900,11 +901,11 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_init(JNIEnv* env, jobject ins
return;
}
NativePanZoomController* oldRef = APZCCallbackHandler::GetInstance()->SetNativePanZoomController(instance);
if (oldRef && !oldRef->isNull()) {
MOZ_ASSERT(false, "Registering a new NPZC when we already have one");
delete oldRef;
}
const auto& newRef = NativePanZoomController::Ref::From(instance);
NativePanZoomController::LocalRef oldRef =
APZCCallbackHandler::GetInstance()->SetNativePanZoomController(newRef);
MOZ_ASSERT(!oldRef, "Registering a new NPZC when we already have one");
}
NS_EXPORT jboolean JNICALL
@ -945,12 +946,10 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_destroy(JNIEnv* env, jobject
return;
}
NativePanZoomController* oldRef = APZCCallbackHandler::GetInstance()->SetNativePanZoomController(nullptr);
if (!oldRef || oldRef->isNull()) {
MOZ_ASSERT(false, "Clearing a non-existent NPZC");
} else {
delete oldRef;
}
NativePanZoomController::LocalRef oldRef =
APZCCallbackHandler::GetInstance()->SetNativePanZoomController(nullptr);
MOZ_ASSERT(oldRef, "Clearing a non-existent NPZC");
}
NS_EXPORT jboolean JNICALL

View File

@ -14,7 +14,6 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::widget::android;
jclass AndroidGeckoEvent::jGeckoEventClass = 0;
jfieldID AndroidGeckoEvent::jActionField = 0;
@ -122,7 +121,6 @@ mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv)
AndroidRect::InitRectClass(jEnv);
AndroidRectF::InitRectFClass(jEnv);
AndroidLayerRendererFrame::InitLayerRendererFrameClass(jEnv);
InitStubs(jEnv);
}
void

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,47 +15,42 @@
#include "GeneratedJNIWrappers.h"
using namespace mozilla;
using namespace mozilla::widget::android;
class AndroidInputStream : public nsIInputStream
{
public:
AndroidInputStream(jobject connection) {
JNIEnv *env = GetJNIForThread();
mBridgeInputStream = env->NewGlobalRef(GeckoAppShell::CreateInputStream(connection));
mBridgeChannel = env->NewGlobalRef(AndroidBridge::ChannelCreate(mBridgeInputStream));
AndroidInputStream(jni::Object::Param connection) {
mBridgeInputStream = widget::GeckoAppShell::CreateInputStream(connection);
mBridgeChannel = AndroidBridge::ChannelCreate(mBridgeInputStream);
}
private:
virtual ~AndroidInputStream() {
JNIEnv *env = GetJNIForThread();
env->DeleteGlobalRef(mBridgeInputStream);
env->DeleteGlobalRef(mBridgeChannel);
}
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
private:
jobject mBridgeInputStream;
jobject mBridgeChannel;
private:
jni::Object::GlobalRef mBridgeInputStream;
jni::Object::GlobalRef mBridgeChannel;
};
NS_IMPL_ISUPPORTS(AndroidInputStream, nsIInputStream)
NS_IMETHODIMP AndroidInputStream::Close(void) {
mozilla::AndroidBridge::InputStreamClose(mBridgeInputStream);
AndroidBridge::InputStreamClose(mBridgeInputStream);
return NS_OK;
}
NS_IMETHODIMP AndroidInputStream::Available(uint64_t *_retval) {
*_retval = mozilla::AndroidBridge::InputStreamAvailable(mBridgeInputStream);
*_retval = AndroidBridge::InputStreamAvailable(mBridgeInputStream);
return NS_OK;
}
NS_IMETHODIMP AndroidInputStream::Read(char *aBuf, uint32_t aCount, uint32_t *_retval) {
return mozilla::AndroidBridge::InputStreamRead(mBridgeChannel, aBuf, aCount, _retval);
return AndroidBridge::InputStreamRead(mBridgeChannel, aBuf, aCount, _retval);
}
NS_IMETHODIMP AndroidInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure, uint32_t aCount, uint32_t *_retval) {
@ -71,27 +66,26 @@ NS_IMETHODIMP AndroidInputStream::IsNonBlocking(bool *_retval) {
class AndroidChannel : public nsBaseChannel
{
private:
AndroidChannel(nsIURI *aURI, jobject aConnection) {
JNIEnv *env = GetJNIForThread();
mConnection = env->NewGlobalRef(aConnection);
AndroidChannel(nsIURI *aURI, jni::Object::Param aConnection) {
mConnection = aConnection;
mURI = aURI;
nsCString type;
jstring jtype = GeckoAppShell::ConnectionGetMimeType(mConnection);
if (jtype)
SetContentType(nsJNICString(jtype, env));
auto type = widget::GeckoAppShell::ConnectionGetMimeType(mConnection);
if (type) {
SetContentType(nsCString(type));
}
}
public:
static AndroidChannel* CreateChannel(nsIURI *aURI) {
nsCString spec;
aURI->GetSpec(spec);
jobject connection = GeckoAppShell::GetConnection(spec);
if (!connection)
return NULL;
return new AndroidChannel(aURI, connection);
auto connection = widget::GeckoAppShell::GetConnection(spec);
return connection ? new AndroidChannel(aURI, connection) : nullptr;
}
~AndroidChannel() {
JNIEnv *env = GetJNIForThread();
env->DeleteGlobalRef(mConnection);
virtual ~AndroidChannel() {
}
virtual nsresult OpenContentStream(bool async, nsIInputStream **result,
@ -100,8 +94,9 @@ public:
NS_ADDREF(*result = stream);
return NS_OK;
}
private:
jobject mConnection;
jni::Object::GlobalRef mConnection;
};
NS_IMPL_ISUPPORTS(nsAndroidProtocolHandler,

View File

@ -80,18 +80,18 @@ public:
mBrowserApp(aBrowserApp), mPoints(aPoints), mTabId(aTabId), mBuffer(aBuffer) {}
virtual nsresult Run() {
jobject buffer = mBuffer->GetObject();
const auto& buffer = jni::Object::Ref::From(mBuffer->GetObject());
nsCOMPtr<nsIDOMWindow> domWindow;
nsCOMPtr<nsIBrowserTab> tab;
mBrowserApp->GetBrowserTab(mTabId, getter_AddRefs(tab));
if (!tab) {
mozilla::widget::android::ThumbnailHelper::SendThumbnail(buffer, mTabId, false, false);
widget::ThumbnailHelper::SendThumbnail(buffer, mTabId, false, false);
return NS_ERROR_FAILURE;
}
tab->GetWindow(getter_AddRefs(domWindow));
if (!domWindow) {
mozilla::widget::android::ThumbnailHelper::SendThumbnail(buffer, mTabId, false, false);
widget::ThumbnailHelper::SendThumbnail(buffer, mTabId, false, false);
return NS_ERROR_FAILURE;
}
@ -99,7 +99,7 @@ public:
bool shouldStore = true;
nsresult rv = AndroidBridge::Bridge()->CaptureThumbnail(domWindow, mPoints[0].x, mPoints[0].y, mTabId, buffer, shouldStore);
mozilla::widget::android::ThumbnailHelper::SendThumbnail(buffer, mTabId, NS_SUCCEEDED(rv), shouldStore);
widget::ThumbnailHelper::SendThumbnail(buffer, mTabId, NS_SUCCEEDED(rv), shouldStore);
return rv;
}
private:
@ -117,7 +117,7 @@ public:
NS_DECL_ISUPPORTS;
nsresult Callback(const nsAString& topic, const nsAString& state) {
mozilla::widget::android::GeckoAppShell::NotifyWakeLockChanged(topic, state);
widget::GeckoAppShell::NotifyWakeLockChanged(topic, state);
return NS_OK;
}
};
@ -312,14 +312,11 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
break;
case AndroidGeckoEvent::PROCESS_OBJECT: {
JNIEnv* const env = AndroidBridge::Bridge()->GetJNIEnv();
AutoLocalJNIFrame frame(env, 1);
switch (curEvent->Action()) {
case AndroidGeckoEvent::ACTION_OBJECT_LAYER_CLIENT:
// SetLayerClient expects a local reference
const jobject obj = env->NewLocalRef(curEvent->Object().wrappedObject());
AndroidBridge::Bridge()->SetLayerClient(env, obj);
AndroidBridge::Bridge()->SetLayerClient(
widget::GeckoLayerClient::Ref::From(curEvent->Object().wrappedObject()));
break;
}
break;
@ -629,8 +626,8 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
mozilla::dom::GamepadMappingType::Standard,
mozilla::dom::kStandardGamepadButtons,
mozilla::dom::kStandardGamepadAxes);
mozilla::widget::android::GeckoAppShell::GamepadAdded(curEvent->ID(),
svc_id);
widget::GeckoAppShell::GamepadAdded(curEvent->ID(),
svc_id);
} else if (curEvent->Action() == AndroidGeckoEvent::ACTION_GAMEPAD_REMOVED) {
svc->RemoveGamepad(curEvent->ID());
}
@ -671,7 +668,7 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
}
if (curEvent->AckNeeded()) {
mozilla::widget::android::GeckoAppShell::AcknowledgeEvent();
widget::GeckoAppShell::AcknowledgeEvent();
}
EVLOG("nsAppShell: -- done event %p %d", (void*)curEvent.get(), curEvent->Type());

View File

@ -43,7 +43,7 @@ nsClipboard::SetData(nsITransferable *aTransferable,
nsAutoString buffer;
supportsString->GetData(buffer);
mozilla::widget::android::Clipboard::SetClipboardText(buffer);
widget::Clipboard::SetClipboardText(buffer);
return NS_OK;
}
@ -84,7 +84,7 @@ nsClipboard::EmptyClipboard(int32_t aWhichClipboard)
{
if (aWhichClipboard != kGlobalClipboard)
return NS_ERROR_NOT_IMPLEMENTED;
mozilla::widget::android::Clipboard::ClearText();
widget::Clipboard::ClearText();
return NS_OK;
}
@ -97,7 +97,7 @@ nsClipboard::HasDataMatchingFlavors(const char **aFlavorList,
*aHasText = false;
if (aWhichClipboard != kGlobalClipboard)
return NS_ERROR_NOT_IMPLEMENTED;
*aHasText = mozilla::widget::android::Clipboard::HasText();
*aHasText = widget::Clipboard::HasText();
return NS_OK;
}

View File

@ -22,6 +22,6 @@ nsIMEPicker::~nsIMEPicker()
/* void show (); */
NS_IMETHODIMP nsIMEPicker::Show()
{
mozilla::widget::android::GeckoAppShell::ShowInputMethodPicker();
widget::GeckoAppShell::ShowInputMethodPicker();
return NS_OK;
}

View File

@ -470,7 +470,7 @@ nsLookAndFeel::GetEchoPasswordImpl()
{
if (!mInitializedShowPassword) {
if (XRE_GetProcessType() == GeckoProcessType_Default) {
mShowPassword = mozilla::widget::android::GeckoAppShell::GetShowPasswordSetting();
mShowPassword = widget::GeckoAppShell::GetShowPasswordSetting();
} else {
ContentChild::GetSingleton()->SendGetShowPasswordSetting(&mShowPassword);
}

View File

@ -66,7 +66,7 @@ nsScreenAndroid::GetColorDepth(int32_t *aColorDepth)
void
nsScreenAndroid::ApplyMinimumBrightness(uint32_t aBrightness)
{
mozilla::widget::android::GeckoAppShell::SetKeepScreenOn(aBrightness == BRIGHTNESS_FULL);
widget::GeckoAppShell::SetKeepScreenOn(aBrightness == BRIGHTNESS_FULL);
}
NS_IMPL_ISUPPORTS(nsScreenManagerAndroid, nsIScreenManager)

View File

@ -355,7 +355,7 @@ nsWindow::GetDefaultScaleInternal()
return density;
}
density = mozilla::widget::android::GeckoAppShell::GetDensity();
density = GeckoAppShell::GetDensity();
if (!density) {
density = 1.0;
@ -517,7 +517,7 @@ nsWindow::SetSizeMode(int32_t aMode)
{
switch (aMode) {
case nsSizeMode_Minimized:
mozilla::widget::android::GeckoAppShell::MoveTaskToBack();
GeckoAppShell::MoveTaskToBack();
break;
case nsSizeMode_Fullscreen:
MakeFullScreen(true);
@ -695,7 +695,7 @@ nsWindow::DispatchEvent(WidgetGUIEvent* aEvent)
NS_IMETHODIMP
nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen*)
{
mozilla::widget::android::GeckoAppShell::SetFullScreen(aFullScreen);
GeckoAppShell::SetFullScreen(aFullScreen);
return NS_OK;
}
@ -1110,9 +1110,9 @@ bool nsWindow::OnMultitouchEvent(AndroidGeckoEvent *ae)
// previous block should not be default-prevented
bool defaultPrevented = isDownEvent ? false : preventDefaultActions;
if (ae->Type() == AndroidGeckoEvent::APZ_INPUT_EVENT) {
mozilla::widget::android::APZCCallbackHandler::GetInstance()->NotifyDefaultPrevented(ae->ApzInputBlockId(), defaultPrevented);
widget::android::APZCCallbackHandler::GetInstance()->NotifyDefaultPrevented(ae->ApzInputBlockId(), defaultPrevented);
} else {
mozilla::widget::android::GeckoAppShell::NotifyDefaultPrevented(defaultPrevented);
GeckoAppShell::NotifyDefaultPrevented(defaultPrevented);
}
sDefaultPreventedNotified = true;
}
@ -1123,9 +1123,9 @@ bool nsWindow::OnMultitouchEvent(AndroidGeckoEvent *ae)
if (isDownEvent) {
if (preventDefaultActions) {
if (ae->Type() == AndroidGeckoEvent::APZ_INPUT_EVENT) {
mozilla::widget::android::APZCCallbackHandler::GetInstance()->NotifyDefaultPrevented(ae->ApzInputBlockId(), true);
widget::android::APZCCallbackHandler::GetInstance()->NotifyDefaultPrevented(ae->ApzInputBlockId(), true);
} else {
mozilla::widget::android::GeckoAppShell::NotifyDefaultPrevented(true);
GeckoAppShell::NotifyDefaultPrevented(true);
}
sDefaultPreventedNotified = true;
} else {
@ -1745,11 +1745,11 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
NotifyIMEOfTextChange(notification);
FlushIMEChanges();
}
mozilla::widget::android::GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
return;
} else if (ae->Action() == AndroidGeckoEvent::IME_UPDATE_CONTEXT) {
mozilla::widget::android::GeckoAppShell::NotifyIMEContext(mInputContext.mIMEState.mEnabled,
GeckoAppShell::NotifyIMEContext(mInputContext.mIMEState.mEnabled,
mInputContext.mHTMLInputType,
mInputContext.mHTMLInputInputmode,
mInputContext.mActionHint);
@ -1762,7 +1762,7 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
if (ae->Action() == AndroidGeckoEvent::IME_SYNCHRONIZE ||
ae->Action() == AndroidGeckoEvent::IME_COMPOSE_TEXT ||
ae->Action() == AndroidGeckoEvent::IME_REPLACE_TEXT) {
mozilla::widget::android::GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
}
return;
}
@ -1777,7 +1777,7 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
case AndroidGeckoEvent::IME_SYNCHRONIZE:
{
FlushIMEChanges();
mozilla::widget::android::GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
}
break;
@ -1822,8 +1822,7 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
}
mIMEKeyEvents.Clear();
FlushIMEChanges();
mozilla::widget::android::GeckoAppShell::NotifyIME(
AndroidBridge::NOTIFY_IME_REPLY_EVENT);
GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
// Break out of the switch block
break;
}
@ -1867,8 +1866,7 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
}
FlushIMEChanges();
mozilla::widget::android::GeckoAppShell::NotifyIME(
AndroidBridge::NOTIFY_IME_REPLY_EVENT);
GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
}
break;
@ -2056,7 +2054,7 @@ nsWindow::NotifyIME(const IMENotification& aIMENotification)
case REQUEST_TO_COMMIT_COMPOSITION:
//ALOGIME("IME: REQUEST_TO_COMMIT_COMPOSITION: s=%d", aState);
RemoveIMEComposition();
mozilla::widget::android::GeckoAppShell::NotifyIME(REQUEST_TO_COMMIT_COMPOSITION);
GeckoAppShell::NotifyIME(REQUEST_TO_COMMIT_COMPOSITION);
return NS_OK;
case REQUEST_TO_CANCEL_COMPOSITION:
ALOGIME("IME: REQUEST_TO_CANCEL_COMPOSITION");
@ -2073,11 +2071,11 @@ nsWindow::NotifyIME(const IMENotification& aIMENotification)
DispatchEvent(&compositionCommitEvent);
}
mozilla::widget::android::GeckoAppShell::NotifyIME(REQUEST_TO_CANCEL_COMPOSITION);
GeckoAppShell::NotifyIME(REQUEST_TO_CANCEL_COMPOSITION);
return NS_OK;
case NOTIFY_IME_OF_FOCUS:
ALOGIME("IME: NOTIFY_IME_OF_FOCUS");
mozilla::widget::android::GeckoAppShell::NotifyIME(NOTIFY_IME_OF_FOCUS);
GeckoAppShell::NotifyIME(NOTIFY_IME_OF_FOCUS);
return NS_OK;
case NOTIFY_IME_OF_BLUR:
ALOGIME("IME: NOTIFY_IME_OF_BLUR");
@ -2089,7 +2087,7 @@ nsWindow::NotifyIME(const IMENotification& aIMENotification)
mIMEComposing = false;
mIMEComposingText.Truncate();
mozilla::widget::android::GeckoAppShell::NotifyIME(NOTIFY_IME_OF_BLUR);
GeckoAppShell::NotifyIME(NOTIFY_IME_OF_BLUR);
return NS_OK;
case NOTIFY_IME_OF_SELECTION_CHANGE:
if (mIMEMaskSelectionUpdate) {
@ -2151,7 +2149,7 @@ nsWindow::SetInputContext(const InputContext& aContext,
if (enabled == IMEState::ENABLED && aAction.UserMightRequestOpenVKB()) {
// Don't reset keyboard when we should simply open the vkb
mozilla::widget::android::GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_OPEN_VKB);
GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_OPEN_VKB);
return;
}
@ -2215,9 +2213,8 @@ nsWindow::FlushIMEChanges()
return;
}
mozilla::widget::android::GeckoAppShell::NotifyIMEChange(
event.mReply.mString, change.mStart,
change.mOldEnd, change.mNewEnd);
GeckoAppShell::NotifyIMEChange(event.mReply.mString, change.mStart,
change.mOldEnd, change.mNewEnd);
}
mIMETextChanges.Clear();
@ -2229,9 +2226,9 @@ nsWindow::FlushIMEChanges()
if (!event.mSucceeded)
return;
mozilla::widget::android::GeckoAppShell::NotifyIMEChange(EmptyString(),
(int32_t) event.GetSelectionStart(),
(int32_t) event.GetSelectionEnd(), -1);
GeckoAppShell::NotifyIMEChange(EmptyString(),
int32_t(event.GetSelectionStart()),
int32_t(event.GetSelectionEnd()), -1);
mIMESelectionChanged = false;
}
}
@ -2327,23 +2324,20 @@ nsWindow::GetIMEUpdatePreference()
void
nsWindow::DrawWindowUnderlay(LayerManagerComposite* aManager, nsIntRect aRect)
{
JNIEnv *env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env);
mozilla::widget::android::GeckoLayerClient* client = AndroidBridge::Bridge()->GetLayerClient();
if (!client || client->isNull()) {
GeckoLayerClient::LocalRef client = AndroidBridge::Bridge()->GetLayerClient();
if (!client) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
jobject frameObj = client->CreateFrame();
AutoLocalJNIFrame jniFrame(client.Env());
auto frameObj = client->CreateFrame();
if (!frameObj) {
NS_WARNING("Warning: unable to obtain a LayerRenderer frame; aborting window underlay draw");
return;
}
mLayerRendererFrame.Init(env, frameObj);
mLayerRendererFrame.Init(client.Env(), frameObj.Get());
if (!WidgetPaintsBackground()) {
return;
}
@ -2368,17 +2362,14 @@ nsWindow::DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect)
PROFILER_LABEL("nsWindow", "DrawWindowOverlay",
js::ProfileEntry::Category::GRAPHICS);
JNIEnv *env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env);
if (mLayerRendererFrame.isNull()) {
NS_WARNING("Warning: do not have a LayerRenderer frame; aborting window overlay draw");
return;
}
mozilla::widget::android::GeckoLayerClient* client = AndroidBridge::Bridge()->GetLayerClient();
GeckoLayerClient::LocalRef client = AndroidBridge::Bridge()->GetLayerClient();
AutoLocalJNIFrame jniFrame(client.Env());
CompositorOGL *compositor = static_cast<CompositorOGL*>(aManager->GetCompositor());
compositor->ResetProgram();
gl::GLContext* gl = compositor->gl();
@ -2391,7 +2382,7 @@ nsWindow::DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect)
if (!mLayerRendererFrame.EndDrawing(&jniFrame)) return;
client->DeactivateProgramAndRestoreState(scissorEnabled,
scissorRect[0], scissorRect[1], scissorRect[2], scissorRect[3]);
mLayerRendererFrame.Dispose(env);
mLayerRendererFrame.Dispose(client.Env());
}
// off-main-thread compositor fields and functions

View File

@ -29,7 +29,6 @@
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
using namespace mozilla::widget::android;
#endif
#ifdef MOZ_WIDGET_GONK
@ -308,7 +307,7 @@ nsSystemInfo::Init()
"android/os/Build", "HARDWARE", str)) {
SetPropertyAsAString(NS_LITERAL_STRING("hardware"), str);
}
bool isTablet = mozilla::widget::android::GeckoAppShell::IsTablet();
bool isTablet = mozilla::widget::GeckoAppShell::IsTablet();
SetPropertyAsBool(NS_LITERAL_STRING("tablet"), isTablet);
// NSPR "version" is the kernel version. For Android we want the Android version.
// Rename SDK version to version and put the kernel version into kernel_version.

View File

@ -579,7 +579,7 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf,
mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION",
"RELEASE",
osVersion);
isTablet = mozilla::widget::android::GeckoAppShell::IsTablet();
isTablet = mozilla::widget::GeckoAppShell::IsTablet();
}
#endif

View File

@ -2058,9 +2058,13 @@ nsLocalFile::Launch()
}
nsAutoCString fileUri = NS_LITERAL_CSTRING("file://") + mPath;
return widget::android::GeckoAppShell::OpenUriExternal(
return widget::GeckoAppShell::OpenUriExternal(
NS_ConvertUTF8toUTF16(fileUri),
NS_ConvertUTF8toUTF16(type)) ? NS_OK : NS_ERROR_FAILURE;
NS_ConvertUTF8toUTF16(type),
EmptyString(),
EmptyString(),
EmptyString(),
EmptyString()) ? NS_OK : NS_ERROR_FAILURE;
#elif defined(MOZ_WIDGET_COCOA)
CFURLRef url;
if (NS_SUCCEEDED(GetCFURL(&url))) {