2010-06-04 00:56:36 +04:00
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2012-05-21 15:12:37 +04:00
* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2.0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/. */
2010-06-04 00:56:36 +04:00
2012-02-04 06:35:58 +04:00
# include "mozilla/layers/CompositorChild.h"
# include "mozilla/layers/CompositorParent.h"
2010-06-04 00:56:36 +04:00
# include <android/log.h>
2011-06-16 13:03:00 +04:00
# include <dlfcn.h>
2010-06-04 00:56:36 +04:00
2011-11-02 19:35:11 +04:00
# include "mozilla/Hal.h"
2010-08-17 12:07:45 +04:00
# include "nsXULAppAPI.h"
2010-06-04 00:56:36 +04:00
# include <prthread.h>
2010-06-30 06:22:08 +04:00
# include "nsXPCOMStrings.h"
2010-06-04 00:56:36 +04:00
# include "AndroidBridge.h"
2013-02-10 03:50:28 +04:00
# include "AndroidJNIWrapper.h"
2013-09-09 16:57:36 +04:00
# include "AndroidBridgeUtilities.h"
2010-06-15 06:17:37 +04:00
# include "nsAppShell.h"
2010-09-30 19:37:36 +04:00
# include "nsOSHelperAppService.h"
2011-04-12 00:41:03 +04:00
# include "nsWindow.h"
2011-06-07 11:38:00 +04:00
# include "mozilla/Preferences.h"
2011-08-04 11:32:57 +04:00
# include "nsThreadUtils.h"
2012-01-30 00:39:30 +04:00
# include "nsIThreadManager.h"
2013-03-01 12:38:47 +04:00
# include "mozilla/dom/mobilemessage/PSms.h"
2012-02-04 10:48:26 +04:00
# include "gfxImageSurface.h"
2013-10-15 07:23:20 +04:00
# include "gfxPlatform.h"
2012-02-04 10:48:26 +04:00
# include "gfxContext.h"
2013-10-15 07:23:20 +04:00
# include "mozilla/gfx/2D.h"
2013-07-24 17:18:05 +04:00
# include "gfxUtils.h"
2012-02-04 10:48:26 +04:00
# include "nsPresContext.h"
# include "nsIDocShell.h"
# include "nsPIDOMWindow.h"
2012-03-20 17:09:45 +04:00
# include "mozilla/dom/ScreenOrientation.h"
2012-06-02 07:50:57 +04:00
# include "nsIDOMWindowUtils.h"
# include "nsIDOMClientRect.h"
2012-07-20 23:20:51 +04:00
# include "StrongPointer.h"
2012-11-07 01:32:07 +04:00
# include "mozilla/ClearOnShutdown.h"
2013-04-26 21:26:46 +04:00
# include "nsPrintfCString.h"
2010-06-04 00:56:36 +04:00
using namespace mozilla ;
2013-11-12 22:41:01 +04:00
using namespace mozilla : : widget : : android ;
2013-10-15 07:23:20 +04:00
using namespace mozilla : : gfx ;
2010-06-04 00:56:36 +04:00
2013-07-19 06:24:15 +04:00
NS_IMPL_ISUPPORTS0 ( nsFilePickerCallback )
2012-04-05 09:50:06 +04:00
2013-08-12 18:58:36 +04:00
StaticRefPtr < AndroidBridge > AndroidBridge : : sBridge ;
2012-08-22 19:56:38 +04:00
static unsigned sJavaEnvThreadIndex = 0 ;
2013-09-25 10:06:21 +04:00
static jobject sGlobalContext = nullptr ;
2012-07-17 18:25:48 +04:00
static void JavaThreadDetachFunc ( void * arg ) ;
2010-06-04 00:56:36 +04:00
2012-07-20 23:20:51 +04:00
// This is a dummy class that can be used in the template for android::sp
class AndroidRefable {
void incStrong ( void * thing ) { }
void decStrong ( void * thing ) { }
} ;
// This isn't in AndroidBridge.h because including StrongPointer.h there is gross
2012-07-30 18:20:58 +04:00
static android : : sp < AndroidRefable > ( * android_SurfaceTexture_getNativeWindow ) ( JNIEnv * env , jobject surfaceTexture ) = nullptr ;
2012-07-20 23:20:51 +04:00
2013-09-09 16:57:36 +04:00
jclass AndroidBridge : : GetClassGlobalRef ( JNIEnv * env , const char * className )
{
jobject classLocalRef = env - > FindClass ( className ) ;
if ( ! classLocalRef ) {
2013-11-19 05:30:00 +04:00
ALOG ( " >>> FATAL JNI ERROR! FindClass(className= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
className ) ;
2013-09-09 16:57:36 +04:00
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 ) ;
2013-10-11 00:42:52 +04:00
classLocalRef = nullptr ;
2013-09-09 16:57:36 +04:00
return static_cast < jclass > ( classGlobalRef ) ;
}
jmethodID AndroidBridge : : GetMethodID ( JNIEnv * env , jclass jClass ,
const char * methodName , const char * methodType )
{
jmethodID methodID = env - > GetMethodID ( jClass , methodName , methodType ) ;
if ( ! methodID ) {
ALOG ( " >>> FATAL JNI ERROR! GetMethodID(methodName= \" %s \" , "
2013-11-19 05:30:00 +04:00
" methodType= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
methodName , methodType ) ;
2013-09-09 16:57:36 +04:00
env - > ExceptionDescribe ( ) ;
MOZ_CRASH ( ) ;
}
return methodID ;
}
jmethodID AndroidBridge : : GetStaticMethodID ( JNIEnv * env , jclass jClass ,
const char * methodName , const char * methodType )
{
jmethodID methodID = env - > GetStaticMethodID ( jClass , methodName , methodType ) ;
if ( ! methodID ) {
ALOG ( " >>> FATAL JNI ERROR! GetStaticMethodID(methodName= \" %s \" , "
2013-11-19 05:30:00 +04:00
" methodType= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
methodName , methodType ) ;
2013-09-09 16:57:36 +04:00
env - > ExceptionDescribe ( ) ;
MOZ_CRASH ( ) ;
}
return methodID ;
}
jfieldID AndroidBridge : : GetFieldID ( JNIEnv * env , jclass jClass ,
const char * fieldName , const char * fieldType )
{
jfieldID fieldID = env - > GetFieldID ( jClass , fieldName , fieldType ) ;
if ( ! fieldID ) {
ALOG ( " >>> FATAL JNI ERROR! GetFieldID(fieldName= \" %s \" , "
2013-11-19 05:30:00 +04:00
" fieldType= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
fieldName , fieldType ) ;
2013-09-09 16:57:36 +04:00
env - > ExceptionDescribe ( ) ;
MOZ_CRASH ( ) ;
}
return fieldID ;
}
jfieldID AndroidBridge : : GetStaticFieldID ( JNIEnv * env , jclass jClass ,
const char * fieldName , const char * fieldType )
{
jfieldID fieldID = env - > GetStaticFieldID ( jClass , fieldName , fieldType ) ;
if ( ! fieldID ) {
ALOG ( " >>> FATAL JNI ERROR! GetStaticFieldID(fieldName= \" %s \" , "
2013-11-19 05:30:00 +04:00
" fieldType= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
fieldName , fieldType ) ;
2013-09-09 16:57:36 +04:00
env - > ExceptionDescribe ( ) ;
MOZ_CRASH ( ) ;
}
return fieldID ;
}
2012-08-01 01:34:06 +04:00
void
2013-09-09 16:57:36 +04:00
AndroidBridge : : ConstructBridge ( JNIEnv * jEnv )
2010-06-04 00:56:36 +04:00
{
/* NSS hack -- bionic doesn't handle recursive unloads correctly,
* because library finalizer functions are called with the dynamic
* linker lock still held . This results in a deadlock when trying
* to call dlclose ( ) while we ' re already inside dlclose ( ) .
* Conveniently , NSS has an env var that can prevent it from unloading .
*/
2012-07-02 23:32:34 +04:00
putenv ( " NSS_DISABLE_UNLOAD=1 " ) ;
2010-06-04 00:56:36 +04:00
2012-07-17 18:25:48 +04:00
PR_NewThreadPrivateIndex ( & sJavaEnvThreadIndex , JavaThreadDetachFunc ) ;
2012-08-01 01:34:06 +04:00
AndroidBridge * bridge = new AndroidBridge ( ) ;
2013-09-09 16:57:36 +04:00
if ( ! bridge - > Init ( jEnv ) ) {
2012-08-01 01:34:06 +04:00
delete bridge ;
2010-06-04 00:56:36 +04:00
}
2012-08-01 01:34:06 +04:00
sBridge = bridge ;
2010-06-04 00:56:36 +04:00
}
2011-09-29 10:19:26 +04:00
bool
2013-09-09 16:57:36 +04:00
AndroidBridge : : Init ( JNIEnv * jEnv )
2010-06-04 00:56:36 +04:00
{
2011-12-06 10:56:04 +04:00
ALOG_BRIDGE ( " AndroidBridge::Init " ) ;
2010-06-04 00:56:36 +04:00
jEnv - > GetJavaVM ( & mJavaVM ) ;
2014-01-18 09:32:24 +04:00
if ( ! mJavaVM ) {
MOZ_CRASH ( ) ; // Nothing we can do here
}
2010-06-04 00:56:36 +04:00
2012-05-04 19:08:47 +04:00
AutoLocalJNIFrame jniFrame ( jEnv ) ;
2012-04-28 00:04:47 +04:00
2012-07-30 18:20:58 +04:00
mJNIEnv = nullptr ;
2013-09-09 16:57:37 +04:00
mThread = - 1 ;
2014-01-06 19:06:04 +04:00
mGLControllerObj = nullptr ;
2011-09-21 20:46:00 +04:00
mOpenedGraphicsLibraries = false ;
2011-06-16 13:03:00 +04:00
mHasNativeBitmapAccess = false ;
2011-09-21 20:46:00 +04:00
mHasNativeWindowAccess = false ;
2012-04-28 00:04:47 +04:00
mHasNativeWindowFallback = false ;
2010-06-04 00:56:36 +04:00
2013-09-09 16:57:36 +04:00
initInit ( ) ;
2010-06-04 00:56:36 +04:00
2013-05-29 08:52:40 +04:00
# ifdef MOZ_WEBSMS_BACKEND
2013-09-09 16:57:36 +04:00
mAndroidSmsMessageClass = getClassGlobalRef ( " android/telephony/SmsMessage " ) ;
jCalculateLength = getStaticMethod ( " calculateLength " , " (Ljava/lang/CharSequence;Z)[I " ) ;
2013-05-29 08:52:40 +04:00
# endif
2013-01-04 10:26:27 +04:00
2013-09-09 16:57:36 +04:00
jStringClass = getClassGlobalRef ( " java/lang/String " ) ;
if ( ! GetStaticIntField ( " android/os/Build$VERSION " , " SDK_INT " , & mAPIVersion , jEnv ) ) {
2012-04-28 00:04:47 +04:00
ALOG_BRIDGE ( " Failed to find API version " ) ;
2013-09-09 16:57:36 +04:00
}
2012-04-28 00:04:47 +04:00
2013-09-09 16:57:36 +04:00
jSurfaceClass = getClassGlobalRef ( " android/view/Surface " ) ;
2013-02-26 18:28:57 +04:00
if ( mAPIVersion < = 8 /* Froyo */ ) {
2013-09-09 16:57:36 +04:00
jSurfacePointerField = getField ( " mSurface " , " I " ) ;
2013-11-04 22:07:03 +04:00
} else if ( mAPIVersion > 8 & & mAPIVersion < 19 /* KitKat */ ) {
2013-09-09 16:57:36 +04:00
jSurfacePointerField = getField ( " mNativeSurface " , " I " ) ;
2013-11-04 22:07:03 +04:00
} else {
// We don't know how to get this, just set it to 0
jSurfacePointerField = 0 ;
2013-02-26 18:28:57 +04:00
}
2013-09-09 16:57:36 +04:00
jclass eglClass = getClassGlobalRef ( " com/google/android/gles_jni/EGLSurfaceImpl " ) ;
2013-02-28 22:28:24 +04:00
if ( eglClass ) {
2013-09-09 16:57:36 +04:00
jEGLSurfacePointerField = getField ( " mEGLSurface " , " I " ) ;
2013-02-28 22:28:24 +04:00
} else {
jEGLSurfacePointerField = 0 ;
}
2012-03-08 19:22:42 +04:00
2010-06-04 00:56:36 +04:00
InitAndroidJavaWrappers ( 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.
2011-10-17 18:59:28 +04:00
return true ;
2010-06-04 00:56:36 +04:00
}
2011-09-29 10:19:26 +04:00
bool
2013-09-09 16:57:37 +04:00
AndroidBridge : : SetMainThread ( pthread_t thr )
2010-06-04 00:56:36 +04:00
{
2011-03-01 07:25:11 +03:00
ALOG_BRIDGE ( " AndroidBridge::SetMainThread " ) ;
2010-06-04 00:56:36 +04:00
if ( thr ) {
mThread = thr ;
2012-01-30 00:39:30 +04:00
mJavaVM - > GetEnv ( ( void * * ) & mJNIEnv , JNI_VERSION_1_2 ) ;
return ( bool ) mJNIEnv ;
2010-06-04 00:56:36 +04:00
}
2012-07-30 18:20:58 +04:00
mJNIEnv = nullptr ;
2013-09-09 16:57:37 +04:00
mThread = - 1 ;
2011-10-17 18:59:28 +04:00
return true ;
2010-06-04 00:56:36 +04:00
}
2013-09-09 16:57:37 +04:00
// Raw JNIEnv variants.
2014-01-04 19:02:17 +04:00
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const char16_t * string , uint32_t len ) {
2013-10-08 22:00:40 +04:00
jstring ret = env - > NewString ( reinterpret_cast < const jchar * > ( string ) , len ) ;
2013-09-09 16:57:37 +04:00
if ( env - > ExceptionCheck ( ) ) {
ALOG_BRIDGE ( " Exceptional exit of: %s " , __PRETTY_FUNCTION__ ) ;
env - > ExceptionDescribe ( ) ;
env - > ExceptionClear ( ) ;
2013-10-11 00:42:52 +04:00
return nullptr ;
2013-09-09 16:57:37 +04:00
}
2012-09-05 08:23:02 +04:00
return ret ;
}
2013-09-09 16:57:37 +04:00
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const nsAString & string ) {
return NewJavaString ( env , string . BeginReading ( ) , string . Length ( ) ) ;
2011-03-02 20:23:02 +03:00
}
2013-09-09 16:57:37 +04:00
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const char * string ) {
return NewJavaString ( env , NS_ConvertUTF8toUTF16 ( string ) ) ;
2010-06-05 01:14:43 +04:00
}
2013-09-09 16:57:37 +04:00
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const nsACString & string ) {
return NewJavaString ( env , NS_ConvertUTF8toUTF16 ( string ) ) ;
2012-03-21 21:52:35 +04:00
}
2013-09-09 16:57:37 +04:00
// AutoLocalJNIFrame variants..
2014-01-04 19:02:17 +04:00
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const char16_t * string , uint32_t len ) {
2013-09-09 16:57:37 +04:00
return NewJavaString ( frame - > GetEnv ( ) , string , len ) ;
2012-02-05 23:51:05 +04:00
}
2013-09-09 16:57:37 +04:00
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const nsAString & string ) {
return NewJavaString ( frame , string . BeginReading ( ) , string . Length ( ) ) ;
2012-02-05 23:51:05 +04:00
}
2013-09-09 16:57:37 +04:00
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const char * string ) {
return NewJavaString ( frame , NS_ConvertUTF8toUTF16 ( string ) ) ;
2010-06-04 00:56:36 +04:00
}
2013-09-09 16:57:37 +04:00
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const nsACString & string ) {
return NewJavaString ( frame , NS_ConvertUTF8toUTF16 ( string ) ) ;
2010-06-04 00:56:36 +04:00
}
2013-11-12 22:41:01 +04:00
extern " C " {
__attribute__ ( ( visibility ( " default " ) ) )
JNIEnv * GetJNIForThread ( )
{
2014-01-18 09:32:24 +04:00
JNIEnv * jEnv = static_cast < JNIEnv * > ( PR_GetThreadPrivate ( sJavaEnvThreadIndex ) ) ;
if ( jEnv ) {
2013-11-12 22:41:01 +04:00
return jEnv ;
}
2014-01-18 09:32:24 +04:00
JavaVM * jVm = mozilla : : AndroidBridge : : GetVM ( ) ;
if ( ! jVm - > GetEnv ( reinterpret_cast < void * * > ( & jEnv ) , JNI_VERSION_1_2 ) | |
! jVm - > AttachCurrentThread ( & jEnv , nullptr ) ) {
MOZ_ASSERT ( jEnv ) ;
PR_SetThreadPrivate ( sJavaEnvThreadIndex , jEnv ) ;
return jEnv ;
2013-11-12 22:41:01 +04:00
}
2014-01-18 09:32:24 +04:00
MOZ_CRASH ( ) ;
return nullptr ; // unreachable
2013-11-12 22:41:01 +04:00
}
}
void AutoGlobalWrappedJavaObject : : Dispose ( ) {
if ( isNull ( ) ) {
return ;
}
GetJNIForThread ( ) - > DeleteGlobalRef ( wrapped_obj ) ;
2014-01-06 19:06:04 +04:00
wrapped_obj = nullptr ;
2013-11-12 22:41:01 +04:00
}
AutoGlobalWrappedJavaObject : : ~ AutoGlobalWrappedJavaObject ( ) {
Dispose ( ) ;
}
2012-07-02 23:32:34 +04:00
static void
2010-09-30 19:37:36 +04:00
getHandlersFromStringArray ( JNIEnv * aJNIEnv , jobjectArray jArr , jsize aLen ,
nsIMutableArray * aHandlersArray ,
nsIHandlerApp * * aDefaultApp ,
const nsAString & aAction = EmptyString ( ) ,
const nsACString & aMimeType = EmptyCString ( ) )
{
nsString empty = EmptyString ( ) ;
for ( jsize i = 0 ; i < aLen ; i + = 4 ) {
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( aJNIEnv , 4 ) ;
2012-07-02 23:32:34 +04:00
nsJNIString name (
2012-04-17 02:31:05 +04:00
static_cast < jstring > ( aJNIEnv - > GetObjectArrayElement ( jArr , i ) ) , aJNIEnv ) ;
2010-09-30 19:37:36 +04:00
nsJNIString isDefault (
2012-04-17 02:31:05 +04:00
static_cast < jstring > ( aJNIEnv - > GetObjectArrayElement ( jArr , i + 1 ) ) , aJNIEnv ) ;
2012-07-02 23:32:34 +04:00
nsJNIString packageName (
2012-04-17 02:31:05 +04:00
static_cast < jstring > ( aJNIEnv - > GetObjectArrayElement ( jArr , i + 2 ) ) , aJNIEnv ) ;
2012-07-02 23:32:34 +04:00
nsJNIString className (
2012-04-17 02:31:05 +04:00
static_cast < jstring > ( aJNIEnv - > GetObjectArrayElement ( jArr , i + 3 ) ) , aJNIEnv ) ;
2010-09-30 19:37:36 +04:00
nsIHandlerApp * app = nsOSHelperAppService : :
CreateAndroidHandlerApp ( name , className , packageName ,
className , aMimeType , aAction ) ;
2012-07-02 23:32:34 +04:00
2011-10-17 18:59:28 +04:00
aHandlersArray - > AppendElement ( app , false ) ;
2010-09-30 19:37:36 +04:00
if ( aDefaultApp & & isDefault . Length ( ) > 0 )
* aDefaultApp = app ;
}
}
2011-09-29 10:19:26 +04:00
bool
2013-09-09 16:57:36 +04:00
AndroidBridge : : GetHandlersForMimeType ( const nsAString & aMimeType ,
2010-09-30 19:37:36 +04:00
nsIMutableArray * aHandlersArray ,
nsIHandlerApp * * aDefaultApp ,
const nsAString & aAction )
2010-06-14 23:04:16 +04:00
{
2011-03-01 07:25:11 +03:00
ALOG_BRIDGE ( " AndroidBridge::GetHandlersForMimeType " ) ;
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 22:41:01 +04:00
jobjectArray arr = GeckoAppShell : : GetHandlersForMimeTypeWrapper ( aMimeType , aAction ) ;
2010-06-16 03:39:43 +04:00
if ( ! arr )
2011-10-17 18:59:28 +04:00
return false ;
2010-06-30 06:22:08 +04:00
2012-01-30 00:39:30 +04:00
jsize len = env - > GetArrayLength ( arr ) ;
2010-06-30 06:22:08 +04:00
2010-09-30 19:37:36 +04:00
if ( ! aHandlersArray )
2010-06-30 06:22:08 +04:00
return len > 0 ;
2012-07-02 23:32:34 +04:00
getHandlersFromStringArray ( env , arr , len , aHandlersArray ,
2010-09-30 19:37:36 +04:00
aDefaultApp , aAction ,
2013-09-09 16:57:36 +04:00
NS_ConvertUTF16toUTF8 ( aMimeType ) ) ;
2011-10-17 18:59:28 +04:00
return true ;
2010-06-30 06:22:08 +04:00
}
2011-09-29 10:19:26 +04:00
bool
2013-09-09 16:57:36 +04:00
AndroidBridge : : GetHandlersForURL ( const nsAString & aURL ,
2011-09-30 11:00:48 +04:00
nsIMutableArray * aHandlersArray ,
nsIHandlerApp * * aDefaultApp ,
const nsAString & aAction )
2010-06-30 06:22:08 +04:00
{
2011-03-01 07:25:11 +03:00
ALOG_BRIDGE ( " AndroidBridge::GetHandlersForURL " ) ;
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 22:41:01 +04:00
jobjectArray arr = GeckoAppShell : : GetHandlersForURLWrapper ( aURL , aAction ) ;
2010-06-30 06:22:08 +04:00
if ( ! arr )
2011-10-17 18:59:28 +04:00
return false ;
2010-06-30 06:22:08 +04:00
2012-01-30 00:39:30 +04:00
jsize len = env - > GetArrayLength ( arr ) ;
2010-06-30 06:22:08 +04:00
2010-09-30 19:37:36 +04:00
if ( ! aHandlersArray )
2010-06-30 06:22:08 +04:00
return len > 0 ;
2012-07-02 23:32:34 +04:00
getHandlersFromStringArray ( env , arr , len , aHandlersArray ,
2010-09-30 19:37:36 +04:00
aDefaultApp , aAction ) ;
2013-09-09 16:57:37 +04:00
return true ;
2010-06-14 23:04:16 +04:00
}
void
2011-03-01 07:25:11 +03:00
AndroidBridge : : GetMimeTypeFromExtensions ( const nsACString & aFileExt , nsCString & aMimeType )
{
ALOG_BRIDGE ( " AndroidBridge::GetMimeTypeFromExtensions " ) ;
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 22:41:01 +04:00
jstring jstrType = GeckoAppShell : : GetMimeTypeFromExtensionsWrapper ( NS_ConvertUTF8toUTF16 ( aFileExt ) ) ;
2013-09-09 16:57:37 +04:00
if ( ! jstrType ) {
2012-05-04 19:08:47 +04:00
return ;
2013-09-09 16:57:37 +04:00
}
2012-04-17 02:31:05 +04:00
nsJNIString jniStr ( jstrType , env ) ;
2012-12-14 02:03:44 +04:00
CopyUTF16toUTF8 ( jniStr . get ( ) , aMimeType ) ;
2010-06-14 23:04:16 +04:00
}
2011-03-08 08:45:43 +03:00
void
2011-09-15 11:40:17 +04:00
AndroidBridge : : GetExtensionFromMimeType ( const nsACString & aMimeType , nsACString & aFileExt )
2011-03-08 08:45:43 +03:00
{
ALOG_BRIDGE ( " AndroidBridge::GetExtensionFromMimeType " ) ;
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 22:41:01 +04:00
jstring jstrExt = GeckoAppShell : : GetExtensionFromMimeTypeWrapper ( NS_ConvertUTF8toUTF16 ( aMimeType ) ) ;
2013-09-09 16:57:37 +04:00
if ( ! jstrExt ) {
2012-05-04 19:08:47 +04:00
return ;
2013-09-09 16:57:37 +04:00
}
2012-04-17 02:31:05 +04:00
nsJNIString jniStr ( jstrExt , env ) ;
2012-12-14 02:03:44 +04:00
CopyUTF16toUTF8 ( jniStr . get ( ) , aFileExt ) ;
2010-06-16 21:20:54 +04:00
}
2010-08-27 03:43:23 +04:00
bool
AndroidBridge : : GetClipboardText ( nsAString & aText )
{
2011-03-01 07:25:11 +03:00
ALOG_BRIDGE ( " AndroidBridge::GetClipboardText " ) ;
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 22:41:01 +04:00
jstring result = Clipboard : : GetClipboardTextWrapper ( ) ;
2013-09-09 16:57:37 +04:00
if ( ! result )
2011-10-17 18:59:28 +04:00
return false ;
2012-05-04 19:08:47 +04:00
2013-09-09 16:57:37 +04:00
nsJNIString jniStr ( result , env ) ;
2010-08-27 03:43:23 +04:00
aText . Assign ( jniStr ) ;
2013-09-09 16:57:37 +04:00
return true ;
2010-08-27 03:43:23 +04:00
}
2010-06-15 06:17:37 +04:00
void
AndroidBridge : : ShowAlertNotification ( const nsAString & aImageUrl ,
const nsAString & aAlertTitle ,
const nsAString & aAlertText ,
const nsAString & aAlertCookie ,
nsIObserver * aAlertListener ,
const nsAString & aAlertName )
{
2013-08-02 22:04:49 +04:00
if ( nsAppShell : : gAppShell & & aAlertListener ) {
// This will remove any observers already registered for this id
2013-09-05 23:32:04 +04:00
nsAppShell : : gAppShell - > PostEvent ( AndroidGeckoEvent : : MakeAddObserver ( aAlertName , aAlertListener ) ) ;
2013-08-02 22:04:49 +04:00
}
2010-06-15 06:17:37 +04:00
2013-11-12 22:41:01 +04:00
GeckoAppShell : : ShowAlertNotificationWrapper ( aImageUrl , aAlertTitle , aAlertText , aAlertCookie , aAlertName ) ;
2010-06-15 06:17:37 +04:00
}
2010-10-07 21:28:27 +04:00
int
AndroidBridge : : GetDPI ( )
{
2012-09-28 23:05:50 +04:00
static int sDPI = 0 ;
if ( sDPI )
return sDPI ;
const int DEFAULT_DPI = 160 ;
2012-01-30 00:39:30 +04:00
2013-11-12 22:41:01 +04:00
sDPI = GeckoAppShell : : GetDpiWrapper ( ) ;
2013-09-09 16:57:37 +04:00
if ( ! sDPI ) {
2012-05-04 19:08:47 +04:00
return DEFAULT_DPI ;
2012-09-28 23:05:50 +04:00
}
2012-05-04 19:08:47 +04:00
2012-09-28 23:05:50 +04:00
return sDPI ;
2010-10-07 21:28:27 +04:00
}
2013-07-04 17:53:25 +04:00
int
AndroidBridge : : GetScreenDepth ( )
{
2013-09-09 16:57:37 +04:00
ALOG_BRIDGE ( " %s " , __PRETTY_FUNCTION__ ) ;
2013-07-04 17:53:25 +04:00
static int sDepth = 0 ;
if ( sDepth )
return sDepth ;
const int DEFAULT_DEPTH = 16 ;
2014-01-18 09:32:24 +04:00
if ( HasEnv ( ) ) {
sDepth = GeckoAppShell : : GetScreenDepthWrapper ( ) ;
}
2013-09-09 16:57:37 +04:00
if ( ! sDepth )
2013-07-04 17:53:25 +04:00
return DEFAULT_DEPTH ;
return sDepth ;
}
2010-09-30 19:37:36 +04:00
void
2012-03-18 20:15:56 +04:00
AndroidBridge : : ShowFilePickerForExtensions ( nsAString & aFilePath , const nsAString & aExtensions )
2012-03-17 01:44:00 +04:00
{
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 22:41:01 +04:00
jstring jstr = GeckoAppShell : : ShowFilePickerForExtensionsWrapper ( aExtensions ) ;
2013-09-09 16:57:37 +04:00
if ( jstr = = nullptr ) {
2012-05-04 19:08:47 +04:00
return ;
2013-09-09 16:57:37 +04:00
}
2012-05-04 19:08:47 +04:00
2012-04-17 02:31:05 +04:00
aFilePath . Assign ( nsJNIString ( jstr , env ) ) ;
2012-03-18 20:15:56 +04:00
}
void
AndroidBridge : : ShowFilePickerForMimeType ( nsAString & aFilePath , const nsAString & aMimeType )
{
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 22:41:01 +04:00
jstring jstr = GeckoAppShell : : ShowFilePickerForMimeTypeWrapper ( aMimeType ) ;
2013-09-09 16:57:37 +04:00
if ( jstr = = nullptr ) {
2012-05-04 19:08:47 +04:00
return ;
2013-09-09 16:57:37 +04:00
}
2012-05-04 19:08:47 +04:00
2012-04-17 02:31:05 +04:00
aFilePath . Assign ( nsJNIString ( jstr , env ) ) ;
2010-09-30 19:37:36 +04:00
}
2010-11-09 05:11:13 +03:00
void
2012-04-05 09:50:06 +04:00
AndroidBridge : : ShowFilePickerAsync ( const nsAString & aMimeType , nsFilePickerCallback * callback )
{
callback - > AddRef ( ) ;
2013-11-12 22:41:01 +04:00
GeckoAppShell : : ShowFilePickerAsyncWrapper ( aMimeType , ( int64_t ) callback ) ;
2010-11-12 23:02:14 +03:00
}
2010-11-22 19:38:02 +03:00
void
2013-09-09 16:57:37 +04:00
AndroidBridge : : Vibrate ( const nsTArray < uint32_t > & aPattern )
2010-11-22 19:38:02 +03:00
{
2013-09-09 16:57:37 +04:00
ALOG_BRIDGE ( " %s " , __PRETTY_FUNCTION__ ) ;
2012-01-30 00:39:30 +04:00
2013-09-09 16:57:37 +04:00
uint32_t len = aPattern . Length ( ) ;
if ( ! len ) {
ALOG_BRIDGE ( " invalid 0-length array " ) ;
2012-01-30 00:39:30 +04:00
return ;
2013-09-09 16:57:37 +04:00
}
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2011-09-30 11:00:48 +04:00
// It's clear if this worth special-casing, but it creates less
// java junk, so dodges the GC.
if ( len = = 1 ) {
jlong d = aPattern [ 0 ] ;
if ( d < 0 ) {
ALOG_BRIDGE ( " invalid vibration duration < 0 " ) ;
return ;
}
2013-11-12 22:41:01 +04:00
GeckoAppShell : : Vibrate1 ( d ) ;
2012-05-04 19:08:45 +04:00
return ;
2011-09-30 11:00:48 +04:00
}
// First element of the array vibrate() expects is how long to wait
// *before* vibrating. For us, this is always 0.
2012-01-30 00:39:30 +04:00
jlongArray array = env - > NewLongArray ( len + 1 ) ;
2011-09-30 11:00:48 +04:00
if ( ! array ) {
ALOG_BRIDGE ( " failed to allocate array " ) ;
return ;
}
2012-07-30 18:20:58 +04:00
jlong * elts = env - > GetLongArrayElements ( array , nullptr ) ;
2011-09-30 11:00:48 +04:00
elts [ 0 ] = 0 ;
2012-08-22 19:56:38 +04:00
for ( uint32_t i = 0 ; i < aPattern . Length ( ) ; + + i ) {
2011-09-30 11:00:48 +04:00
jlong d = aPattern [ i ] ;
if ( d < 0 ) {
ALOG_BRIDGE ( " invalid vibration duration < 0 " ) ;
2012-01-30 00:39:30 +04:00
env - > ReleaseLongArrayElements ( array , elts , JNI_ABORT ) ;
2011-09-30 11:00:48 +04:00
return ;
}
elts [ i + 1 ] = d ;
}
2012-01-30 00:39:30 +04:00
env - > ReleaseLongArrayElements ( array , elts , 0 ) ;
2011-09-30 11:00:48 +04:00
2013-11-12 22:41:01 +04:00
GeckoAppShell : : VibrateA ( array , - 1 /*don't repeat*/ ) ;
2011-02-27 18:50:56 +03:00
}
2011-03-30 22:04:41 +04:00
void
AndroidBridge : : GetSystemColors ( AndroidSystemColors * aColors )
{
2012-07-30 18:20:58 +04:00
NS_ASSERTION ( aColors ! = nullptr , " AndroidBridge::GetSystemColors: aColors is null! " ) ;
2011-03-30 22:04:41 +04:00
if ( ! aColors )
return ;
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2011-03-30 22:04:41 +04:00
2013-11-12 22:41:01 +04:00
jintArray arr = GeckoAppShell : : GetSystemColoursWrapper ( ) ;
2011-03-30 22:04:41 +04:00
if ( ! arr )
return ;
2012-08-22 19:56:38 +04:00
uint32_t len = static_cast < uint32_t > ( env - > GetArrayLength ( arr ) ) ;
2012-01-30 00:39:30 +04:00
jint * elements = env - > GetIntArrayElements ( arr , 0 ) ;
2011-03-30 22:04:41 +04:00
2012-08-22 19:56:38 +04:00
uint32_t colorsCount = sizeof ( AndroidSystemColors ) / sizeof ( nscolor ) ;
2011-03-30 22:04:41 +04:00
if ( len < colorsCount )
colorsCount = len ;
// Convert Android colors to nscolor by switching R and B in the ARGB 32 bit value
nscolor * colors = ( nscolor * ) aColors ;
2012-08-22 19:56:38 +04:00
for ( uint32_t i = 0 ; i < colorsCount ; i + + ) {
uint32_t androidColor = static_cast < uint32_t > ( elements [ i ] ) ;
uint8_t r = ( androidColor & 0x00ff0000 ) > > 16 ;
uint8_t b = ( androidColor & 0x000000ff ) ;
2012-07-12 20:52:52 +04:00
colors [ i ] = ( androidColor & 0xff00ff00 ) | ( b < < 16 ) | r ;
2011-03-30 22:04:41 +04:00
}
2012-01-30 00:39:30 +04:00
env - > ReleaseIntArrayElements ( arr , elements , 0 ) ;
2011-03-30 22:04:41 +04:00
}
2011-06-14 01:02:13 +04:00
void
2012-08-22 19:56:38 +04:00
AndroidBridge : : GetIconForExtension ( const nsACString & aFileExt , uint32_t aIconSize , uint8_t * const aBuf )
2011-06-14 01:02:13 +04:00
{
ALOG_BRIDGE ( " AndroidBridge::GetIconForExtension " ) ;
2012-07-30 18:20:58 +04:00
NS_ASSERTION ( aBuf ! = nullptr , " AndroidBridge::GetIconForExtension: aBuf is null! " ) ;
2011-06-14 01:02:13 +04:00
if ( ! aBuf )
return ;
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2011-06-14 01:02:13 +04:00
2013-11-12 22:41:01 +04:00
jbyteArray arr = GeckoAppShell : : GetIconForExtensionWrapper ( NS_ConvertUTF8toUTF16 ( aFileExt ) , aIconSize ) ;
2012-05-04 19:08:47 +04:00
2012-07-30 18:20:58 +04:00
NS_ASSERTION ( arr ! = nullptr , " AndroidBridge::GetIconForExtension: Returned pixels array is null! " ) ;
2011-06-14 01:02:13 +04:00
if ( ! arr )
return ;
2012-08-22 19:56:38 +04:00
uint32_t len = static_cast < uint32_t > ( env - > GetArrayLength ( arr ) ) ;
2012-01-30 00:39:30 +04:00
jbyte * elements = env - > GetByteArrayElements ( arr , 0 ) ;
2011-06-14 01:02:13 +04:00
2012-08-22 19:56:38 +04:00
uint32_t bufSize = aIconSize * aIconSize * 4 ;
2011-06-14 01:02:13 +04:00
NS_ASSERTION ( len = = bufSize , " AndroidBridge::GetIconForExtension: Pixels array is incomplete! " ) ;
if ( len = = bufSize )
memcpy ( aBuf , elements , bufSize ) ;
2012-01-30 00:39:30 +04:00
env - > ReleaseByteArrayElements ( arr , elements , 0 ) ;
2011-06-14 01:02:13 +04:00
}
2010-06-04 00:56:36 +04:00
void
2012-07-13 18:19:46 +04:00
AndroidBridge : : SetLayerClient ( JNIEnv * env , jobject jobj )
2012-02-17 18:16:14 +04:00
{
2012-07-13 18:19:46 +04:00
// 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.
// We therefore need to link up the new java objects to Gecko, and that's what
// we do here.
2013-10-11 00:42:52 +04:00
bool resetting = ( mLayerClient ! = nullptr ) ;
2012-07-13 18:19:46 +04:00
if ( resetting ) {
// clear out the old layer client
delete mLayerClient ;
2013-10-11 00:42:52 +04:00
mLayerClient = nullptr ;
2012-07-13 18:19:46 +04:00
}
2013-11-12 22:41:01 +04:00
mLayerClient = GeckoLayerClient : : Wrap ( jobj ) ;
2012-07-13 18:19:46 +04:00
if ( resetting ) {
2013-02-05 00:13:17 +04:00
// since we are re-linking the new java objects to Gecko, we need to get
// the viewport from the compositor (since the Java copy was thrown away)
// and we do that by setting the first-paint flag.
nsWindow : : ForceIsFirstPaint ( ) ;
2012-07-13 18:19:46 +04:00
}
2010-06-04 00:56:36 +04:00
}
2012-02-07 01:53:09 +04:00
void
2013-02-28 22:28:23 +04:00
AndroidBridge : : RegisterCompositor ( JNIEnv * env )
2012-01-26 23:23:13 +04:00
{
2014-01-06 19:06:04 +04:00
if ( mGLControllerObj ! = nullptr & & ! mGLControllerObj - > isNull ( ) ) {
2013-02-28 22:28:24 +04:00
// we already have this set up, no need to do it again
return ;
}
2013-11-12 22:41:01 +04:00
jobject glController = LayerView : : RegisterCompositorWrapper ( ) ;
2013-09-09 16:57:37 +04:00
if ( ! glController ) {
2012-05-04 19:08:47 +04:00
return ;
2013-09-09 16:57:37 +04:00
}
2012-02-02 01:18:35 +04:00
2013-11-12 22:41:01 +04:00
mGLControllerObj = GLController : : Wrap ( glController ) ;
2012-02-07 01:53:09 +04:00
}
EGLSurface
2013-11-15 20:28:59 +04:00
AndroidBridge : : CreateEGLSurfaceForCompositor ( )
2012-02-07 01:53:09 +04:00
{
2013-02-28 22:28:24 +04:00
if ( ! jEGLSurfacePointerField ) {
2013-10-11 00:42:52 +04:00
return nullptr ;
2013-02-28 22:28:24 +04:00
}
2013-11-15 20:28:59 +04:00
MOZ_ASSERT ( mGLControllerObj , " AndroidBridge::CreateEGLSurfaceForCompositor called with a null GL controller ref " ) ;
2013-02-28 22:28:24 +04:00
JNIEnv * env = GetJNIForThread ( ) ; // called on the compositor thread
2013-09-09 16:57:37 +04:00
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 22:41:01 +04:00
jobject eglSurface = mGLControllerObj - > CreateEGLSurfaceForCompositorWrapper ( ) ;
2013-09-09 16:57:37 +04:00
if ( ! eglSurface )
2013-10-11 00:42:52 +04:00
return nullptr ;
2013-02-28 22:28:24 +04:00
2013-09-09 16:57:37 +04:00
EGLSurface ret = reinterpret_cast < EGLSurface > ( env - > GetIntField ( eglSurface , jEGLSurfacePointerField ) ) ;
return ret ;
2012-01-26 23:23:13 +04:00
}
2011-02-28 19:32:05 +03:00
bool
2013-09-09 16:57:36 +04:00
AndroidBridge : : GetStaticIntField ( const char * className , const char * fieldName , int32_t * aInt , JNIEnv * jEnv /* = nullptr */ )
2011-02-28 19:32:05 +03:00
{
2011-03-01 07:25:11 +03:00
ALOG_BRIDGE ( " AndroidBridge::GetStaticIntField %s " , fieldName ) ;
2012-04-28 00:04:47 +04:00
2013-09-09 16:57:36 +04:00
if ( ! jEnv ) {
2014-01-18 09:32:24 +04:00
if ( ! HasEnv ( ) ) {
return false ;
}
2013-09-09 16:57:36 +04:00
jEnv = GetJNIEnv ( ) ;
2012-04-28 00:04:47 +04:00
}
2012-01-30 00:39:30 +04:00
2013-09-09 16:57:36 +04:00
initInit ( ) ;
getClassGlobalRef ( className ) ;
jfieldID field = getStaticField ( fieldName , " I " ) ;
2011-02-28 19:32:05 +03:00
2013-09-09 16:57:36 +04:00
if ( ! field ) {
jEnv - > DeleteGlobalRef ( jClass ) ;
2011-02-28 19:32:05 +03:00
return false ;
2013-09-09 16:57:36 +04:00
}
2011-02-28 19:32:05 +03:00
2013-09-09 16:57:36 +04:00
* aInt = static_cast < int32_t > ( jEnv - > GetStaticIntField ( jClass , field ) ) ;
2011-02-28 19:32:05 +03:00
2013-09-09 16:57:36 +04:00
jEnv - > DeleteGlobalRef ( jClass ) ;
2011-02-28 19:32:05 +03:00
return true ;
}
2010-09-11 17:20:20 +04:00
bool
2013-09-09 16:57:36 +04:00
AndroidBridge : : GetStaticStringField ( const char * className , const char * fieldName , nsAString & result , JNIEnv * jEnv /* = nullptr */ )
2010-09-11 17:20:20 +04:00
{
2012-05-04 19:08:47 +04:00
ALOG_BRIDGE ( " AndroidBridge::GetStaticStringField %s " , fieldName ) ;
2011-03-01 07:25:11 +03:00
2013-09-09 16:57:36 +04:00
if ( ! jEnv ) {
2014-01-18 09:32:24 +04:00
if ( ! HasEnv ( ) ) {
return false ;
}
2013-09-09 16:57:36 +04:00
jEnv = GetJNIEnv ( ) ;
2012-04-28 00:04:47 +04:00
}
2012-01-30 00:39:30 +04:00
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( jEnv , 1 ) ;
2013-09-09 16:57:36 +04:00
initInit ( ) ;
getClassGlobalRef ( className ) ;
jfieldID field = getStaticField ( fieldName , " Ljava/lang/String; " ) ;
2010-09-11 17:20:20 +04:00
2013-09-09 16:57:36 +04:00
if ( ! field ) {
jEnv - > DeleteGlobalRef ( jClass ) ;
2010-09-11 17:20:20 +04:00
return false ;
2013-09-09 16:57:36 +04:00
}
2010-09-11 17:20:20 +04:00
2013-09-09 16:57:36 +04:00
jstring jstr = ( jstring ) jEnv - > GetStaticObjectField ( jClass , field ) ;
jEnv - > DeleteGlobalRef ( jClass ) ;
2010-09-11 17:20:20 +04:00
if ( ! jstr )
return false ;
2013-09-09 16:57:36 +04:00
result . Assign ( nsJNIString ( jstr , jEnv ) ) ;
2010-09-11 17:20:20 +04:00
return true ;
}
2010-06-04 00:56:36 +04:00
// Available for places elsewhere in the code to link to.
2011-09-29 10:19:26 +04:00
bool
2013-09-09 16:57:37 +04:00
mozilla_AndroidBridge_SetMainThread ( pthread_t thr )
2010-06-04 00:56:36 +04:00
{
return AndroidBridge : : Bridge ( ) - > SetMainThread ( thr ) ;
}
2012-04-28 00:04:47 +04:00
void *
AndroidBridge : : GetNativeSurface ( JNIEnv * env , jobject surface ) {
2013-02-26 18:28:57 +04:00
if ( ! env | | ! mHasNativeWindowFallback | | ! jSurfacePointerField )
2012-07-30 18:20:58 +04:00
return nullptr ;
2012-04-28 00:04:47 +04:00
return ( void * ) env - > GetIntField ( surface , jSurfacePointerField ) ;
}
2011-09-21 20:46:00 +04:00
void
AndroidBridge : : OpenGraphicsLibraries ( )
2011-06-16 13:03:00 +04:00
{
2011-09-21 20:46:00 +04:00
if ( ! mOpenedGraphicsLibraries ) {
2011-06-16 13:03:00 +04:00
// Try to dlopen libjnigraphics.so for direct bitmap access on
// Android 2.2+ (API level 8)
2011-09-21 20:46:00 +04:00
mOpenedGraphicsLibraries = true ;
2011-09-28 22:43:02 +04:00
mHasNativeWindowAccess = false ;
2012-04-28 00:04:47 +04:00
mHasNativeWindowFallback = false ;
2011-09-28 22:43:02 +04:00
mHasNativeBitmapAccess = false ;
2011-06-16 13:03:00 +04:00
2012-01-13 10:23:02 +04:00
void * handle = dlopen ( " libjnigraphics.so " , RTLD_LAZY | RTLD_LOCAL ) ;
2011-09-21 20:46:00 +04:00
if ( handle ) {
AndroidBitmap_getInfo = ( int ( * ) ( JNIEnv * , jobject , void * ) ) dlsym ( handle , " AndroidBitmap_getInfo " ) ;
AndroidBitmap_lockPixels = ( int ( * ) ( JNIEnv * , jobject , void * * ) ) dlsym ( handle , " AndroidBitmap_lockPixels " ) ;
AndroidBitmap_unlockPixels = ( int ( * ) ( JNIEnv * , jobject ) ) dlsym ( handle , " AndroidBitmap_unlockPixels " ) ;
2011-06-16 13:03:00 +04:00
2011-09-28 22:43:02 +04:00
mHasNativeBitmapAccess = AndroidBitmap_getInfo & & AndroidBitmap_lockPixels & & AndroidBitmap_unlockPixels ;
ALOG_BRIDGE ( " Successfully opened libjnigraphics.so, have native bitmap access? %d " , mHasNativeBitmapAccess ) ;
2011-09-21 20:46:00 +04:00
}
2011-06-16 13:03:00 +04:00
2011-09-21 20:46:00 +04:00
// Try to dlopen libandroid.so for and native window access on
// Android 2.3+ (API level 9)
2012-01-13 10:23:02 +04:00
handle = dlopen ( " libandroid.so " , RTLD_LAZY | RTLD_LOCAL ) ;
2011-09-21 20:46:00 +04:00
if ( handle ) {
ANativeWindow_fromSurface = ( void * ( * ) ( JNIEnv * , jobject ) ) dlsym ( handle , " ANativeWindow_fromSurface " ) ;
ANativeWindow_release = ( void ( * ) ( void * ) ) dlsym ( handle , " ANativeWindow_release " ) ;
ANativeWindow_setBuffersGeometry = ( int ( * ) ( void * , int , int , int ) ) dlsym ( handle , " ANativeWindow_setBuffersGeometry " ) ;
ANativeWindow_lock = ( int ( * ) ( void * , void * , void * ) ) dlsym ( handle , " ANativeWindow_lock " ) ;
ANativeWindow_unlockAndPost = ( int ( * ) ( void * ) ) dlsym ( handle , " ANativeWindow_unlockAndPost " ) ;
2011-09-21 20:46:00 +04:00
2012-07-20 23:20:51 +04:00
// This is only available in Honeycomb and ICS. It was removed in Jelly Bean
ANativeWindow_fromSurfaceTexture = ( void * ( * ) ( JNIEnv * , jobject ) ) dlsym ( handle , " ANativeWindow_fromSurfaceTexture " ) ;
2011-09-28 22:43:02 +04:00
mHasNativeWindowAccess = ANativeWindow_fromSurface & & ANativeWindow_release & & ANativeWindow_lock & & ANativeWindow_unlockAndPost ;
ALOG_BRIDGE ( " Successfully opened libandroid.so, have native window access? %d " , mHasNativeWindowAccess ) ;
}
2012-04-28 00:04:47 +04:00
2012-07-20 23:20:51 +04:00
// We need one symbol from here on Jelly Bean
handle = dlopen ( " libandroid_runtime.so " , RTLD_LAZY | RTLD_LOCAL ) ;
if ( handle ) {
android_SurfaceTexture_getNativeWindow = ( android : : sp < AndroidRefable > ( * ) ( JNIEnv * , jobject ) ) dlsym ( handle , " _ZN7android38android_SurfaceTexture_getNativeWindowEP7_JNIEnvP8_jobject " ) ;
}
2012-04-28 00:04:47 +04:00
if ( mHasNativeWindowAccess )
return ;
// Look up Surface functions, used for native window (surface) fallback
handle = dlopen ( " libsurfaceflinger_client.so " , RTLD_LAZY ) ;
if ( handle ) {
Surface_lock = ( int ( * ) ( void * , void * , void * , bool ) ) dlsym ( handle , " _ZN7android7Surface4lockEPNS0_11SurfaceInfoEPNS_6RegionEb " ) ;
Surface_unlockAndPost = ( int ( * ) ( void * ) ) dlsym ( handle , " _ZN7android7Surface13unlockAndPostEv " ) ;
handle = dlopen ( " libui.so " , RTLD_LAZY ) ;
if ( handle ) {
Region_constructor = ( void ( * ) ( void * ) ) dlsym ( handle , " _ZN7android6RegionC1Ev " ) ;
Region_set = ( void ( * ) ( void * , void * ) ) dlsym ( handle , " _ZN7android6Region3setERKNS_4RectE " ) ;
mHasNativeWindowFallback = Surface_lock & & Surface_unlockAndPost & & Region_constructor & & Region_set ;
}
}
2011-09-24 19:51:46 +04:00
}
2011-09-21 20:46:00 +04:00
}
2011-08-04 11:32:57 +04:00
namespace mozilla {
class TracerRunnable : public nsRunnable {
public :
TracerRunnable ( ) {
mTracerLock = new Mutex ( " TracerRunnable " ) ;
mTracerCondVar = new CondVar ( * mTracerLock , " TracerRunnable " ) ;
mMainThread = do_GetMainThread ( ) ;
2012-07-02 23:32:34 +04:00
2011-08-04 11:32:57 +04:00
}
~ TracerRunnable ( ) {
delete mTracerCondVar ;
delete mTracerLock ;
2012-07-30 18:20:58 +04:00
mTracerLock = nullptr ;
mTracerCondVar = nullptr ;
2011-08-04 11:32:57 +04:00
}
virtual nsresult Run ( ) {
MutexAutoLock lock ( * mTracerLock ) ;
if ( ! AndroidBridge : : Bridge ( ) )
return NS_OK ;
2012-07-02 23:32:34 +04:00
2012-04-04 13:15:10 +04:00
mHasRun = true ;
2011-08-04 11:32:57 +04:00
mTracerCondVar - > Notify ( ) ;
return NS_OK ;
}
2012-07-02 23:32:34 +04:00
2011-08-04 11:32:57 +04:00
bool Fire ( ) {
if ( ! mTracerLock | | ! mTracerCondVar )
return false ;
MutexAutoLock lock ( * mTracerLock ) ;
2012-04-04 13:15:10 +04:00
mHasRun = false ;
2011-08-04 11:32:57 +04:00
mMainThread - > Dispatch ( this , NS_DISPATCH_NORMAL ) ;
while ( ! mHasRun )
mTracerCondVar - > Wait ( ) ;
return true ;
}
void Signal ( ) {
MutexAutoLock lock ( * mTracerLock ) ;
2012-04-04 13:15:10 +04:00
mHasRun = true ;
2011-08-04 11:32:57 +04:00
mTracerCondVar - > Notify ( ) ;
}
private :
Mutex * mTracerLock ;
CondVar * mTracerCondVar ;
2012-04-04 13:15:10 +04:00
bool mHasRun ;
2011-08-04 11:32:57 +04:00
nsCOMPtr < nsIThread > mMainThread ;
} ;
2013-08-12 18:58:36 +04:00
StaticRefPtr < TracerRunnable > sTracerRunnable ;
2011-08-04 11:32:57 +04:00
bool InitWidgetTracing ( ) {
if ( ! sTracerRunnable )
sTracerRunnable = new TracerRunnable ( ) ;
return true ;
}
void CleanUpWidgetTracing ( ) {
2012-07-30 18:20:58 +04:00
sTracerRunnable = nullptr ;
2011-08-04 11:32:57 +04:00
}
bool FireAndWaitForTracerEvent ( ) {
if ( sTracerRunnable )
return sTracerRunnable - > Fire ( ) ;
return false ;
}
2012-07-02 23:32:34 +04:00
void SignalTracerThread ( )
{
if ( sTracerRunnable )
return sTracerRunnable - > Signal ( ) ;
}
2011-08-04 11:32:57 +04:00
}
2011-09-21 20:46:00 +04:00
bool
AndroidBridge : : HasNativeBitmapAccess ( )
{
OpenGraphicsLibraries ( ) ;
2011-06-16 13:03:00 +04:00
return mHasNativeBitmapAccess ;
}
bool
AndroidBridge : : ValidateBitmap ( jobject bitmap , int width , int height )
{
// This structure is defined in Android API level 8's <android/bitmap.h>
// Because we can't depend on this, we get the function pointers via dlsym
// and define this struct ourselves.
struct BitmapInfo {
uint32_t width ;
uint32_t height ;
uint32_t stride ;
uint32_t format ;
uint32_t flags ;
} ;
int err ;
struct BitmapInfo info = { 0 , } ;
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ( err = AndroidBitmap_getInfo ( env , bitmap , & info ) ) ! = 0 ) {
2011-06-16 13:03:00 +04:00
ALOG_BRIDGE ( " AndroidBitmap_getInfo failed! (error %d) " , err ) ;
return false ;
}
2012-07-12 20:52:52 +04:00
if ( ( int ) info . width ! = width | | ( int ) info . height ! = height )
2011-06-16 13:03:00 +04:00
return false ;
return true ;
}
2011-09-27 04:25:41 +04:00
bool
2012-08-22 19:56:38 +04:00
AndroidBridge : : InitCamera ( const nsCString & contentType , uint32_t camera , uint32_t * width , uint32_t * height , uint32_t * fps )
2011-09-27 04:25:41 +04:00
{
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 22:41:01 +04:00
jintArray arr = GeckoAppShell : : InitCameraWrapper ( NS_ConvertUTF8toUTF16 ( contentType ) , ( int32_t ) camera , ( int32_t ) width , ( int32_t ) height ) ;
2011-09-27 04:25:41 +04:00
if ( ! arr )
return false ;
2012-01-30 00:39:30 +04:00
jint * elements = env - > GetIntArrayElements ( arr , 0 ) ;
2011-09-27 04:25:41 +04:00
* width = elements [ 1 ] ;
* height = elements [ 2 ] ;
* fps = elements [ 3 ] ;
bool res = elements [ 0 ] = = 1 ;
2012-01-30 00:39:30 +04:00
env - > ReleaseIntArrayElements ( arr , elements , 0 ) ;
2011-09-27 04:25:41 +04:00
return res ;
}
2011-11-02 19:35:11 +04:00
void
AndroidBridge : : GetCurrentBatteryInformation ( hal : : BatteryInformation * aBatteryInfo )
{
ALOG_BRIDGE ( " AndroidBridge::GetCurrentBatteryInformation " ) ;
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2011-11-02 19:35:11 +04:00
// To prevent calling too many methods through JNI, the Java method returns
2011-11-09 12:56:37 +04:00
// an array of double even if we actually want a double and a boolean.
2013-11-12 22:41:01 +04:00
jdoubleArray arr = GeckoAppShell : : GetCurrentBatteryInformationWrapper ( ) ;
2012-01-30 00:39:30 +04:00
if ( ! arr | | env - > GetArrayLength ( arr ) ! = 3 ) {
2011-11-02 19:35:11 +04:00
return ;
}
2012-01-30 00:39:30 +04:00
jdouble * info = env - > GetDoubleArrayElements ( arr , 0 ) ;
2011-11-02 19:35:11 +04:00
aBatteryInfo - > level ( ) = info [ 0 ] ;
aBatteryInfo - > charging ( ) = info [ 1 ] = = 1.0f ;
2011-11-09 18:13:37 +04:00
aBatteryInfo - > remainingTime ( ) = info [ 2 ] ;
2011-11-02 19:35:11 +04:00
2012-01-30 00:39:30 +04:00
env - > ReleaseDoubleArrayElements ( arr , info , 0 ) ;
2011-11-02 19:35:11 +04:00
}
2011-11-15 07:12:14 +04:00
void
AndroidBridge : : HandleGeckoMessage ( const nsAString & aMessage , nsAString & aRet )
{
ALOG_BRIDGE ( " %s " , __PRETTY_FUNCTION__ ) ;
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2011-11-15 07:12:14 +04:00
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 22:41:01 +04:00
jstring returnMessage = GeckoAppShell : : HandleGeckoMessageWrapper ( aMessage ) ;
2013-09-09 16:57:37 +04:00
if ( ! returnMessage )
2012-05-04 19:08:47 +04:00
return ;
2011-11-15 07:12:14 +04:00
2012-04-17 01:25:04 +04:00
nsJNIString jniStr ( returnMessage , env ) ;
2011-11-15 07:12:14 +04:00
aRet . Assign ( jniStr ) ;
ALOG_BRIDGE ( " leaving %s " , __PRETTY_FUNCTION__ ) ;
}
2013-01-04 10:26:27 +04:00
nsresult
AndroidBridge : : GetSegmentInfoForText ( const nsAString & aText ,
2013-08-09 17:25:53 +04:00
nsIMobileMessageCallback * aRequest )
2011-11-25 13:48:51 +04:00
{
2013-05-29 08:52:40 +04:00
# ifndef MOZ_WEBSMS_BACKEND
return NS_ERROR_FAILURE ;
# else
2013-01-04 10:26:27 +04:00
ALOG_BRIDGE ( " AndroidBridge::GetSegmentInfoForText " ) ;
2013-08-09 17:25:53 +04:00
dom : : mobilemessage : : SmsSegmentInfoData data ;
data . segments ( ) = 0 ;
data . charsPerSegment ( ) = 0 ;
data . charsAvailableInLastSegment ( ) = 0 ;
2011-11-25 13:48:51 +04:00
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 2 ) ;
2012-12-14 02:03:44 +04:00
jstring jText = NewJavaString ( & jniFrame , aText ) ;
2013-01-04 10:26:27 +04:00
jobject obj = env - > CallStaticObjectMethod ( mAndroidSmsMessageClass ,
jCalculateLength , jText , JNI_FALSE ) ;
2012-05-04 19:08:47 +04:00
if ( jniFrame . CheckForException ( ) )
2013-01-04 10:26:27 +04:00
return NS_ERROR_FAILURE ;
2012-05-04 19:08:47 +04:00
2013-01-04 10:26:27 +04:00
jintArray arr = static_cast < jintArray > ( obj ) ;
if ( ! arr | | env - > GetArrayLength ( arr ) ! = 4 )
return NS_ERROR_FAILURE ;
jint * info = env - > GetIntArrayElements ( arr , JNI_FALSE ) ;
2013-08-09 17:25:53 +04:00
data . segments ( ) = info [ 0 ] ; // msgCount
data . charsPerSegment ( ) = info [ 2 ] ; // codeUnitsRemaining
2013-01-04 10:26:27 +04:00
// segmentChars = (codeUnitCount + codeUnitsRemaining) / msgCount
2013-08-09 17:25:53 +04:00
data . charsAvailableInLastSegment ( ) = ( info [ 1 ] + info [ 2 ] ) / info [ 0 ] ;
2013-01-04 10:26:27 +04:00
env - > ReleaseIntArrayElements ( arr , info , JNI_ABORT ) ;
2013-08-09 17:25:53 +04:00
// TODO Bug 908598 - Should properly use |QueueSmsRequest(...)| to queue up
// the nsIMobileMessageCallback just like other functions.
nsCOMPtr < nsIDOMMozSmsSegmentInfo > info = new SmsSegmentInfo ( data ) ;
return aRequest - > NotifySegmentInfoForTextGot ( info ) ;
2013-05-29 08:52:40 +04:00
# endif
2011-11-25 13:48:51 +04:00
}
2011-11-21 03:00:46 +04:00
void
2013-03-09 11:22:02 +04:00
AndroidBridge : : SendMessage ( const nsAString & aNumber ,
const nsAString & aMessage ,
nsIMobileMessageCallback * aRequest )
2011-11-21 03:00:46 +04:00
{
ALOG_BRIDGE ( " AndroidBridge::SendMessage " ) ;
2013-01-25 23:00:00 +04:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-07 01:32:07 +04:00
2013-11-12 22:41:01 +04:00
GeckoAppShell : : SendMessageWrapper ( aNumber , aMessage , requestId ) ;
2011-11-21 03:00:46 +04:00
}
2011-12-23 02:08:58 +04:00
void
2013-03-09 11:22:02 +04:00
AndroidBridge : : GetMessage ( int32_t aMessageId , nsIMobileMessageCallback * aRequest )
2011-12-23 02:08:58 +04:00
{
ALOG_BRIDGE ( " AndroidBridge::GetMessage " ) ;
2013-01-25 23:00:00 +04:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-07 01:32:07 +04:00
2013-11-12 22:41:01 +04:00
GeckoAppShell : : GetMessageWrapper ( aMessageId , requestId ) ;
2011-12-23 02:08:58 +04:00
}
2011-12-23 02:15:28 +04:00
void
2013-03-09 11:22:02 +04:00
AndroidBridge : : DeleteMessage ( int32_t aMessageId , nsIMobileMessageCallback * aRequest )
2011-12-23 02:15:28 +04:00
{
ALOG_BRIDGE ( " AndroidBridge::DeleteMessage " ) ;
2013-01-25 23:00:00 +04:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-07 01:32:07 +04:00
2013-11-12 22:41:01 +04:00
GeckoAppShell : : DeleteMessageWrapper ( aMessageId , requestId ) ;
2011-12-23 02:15:28 +04:00
}
2011-12-20 12:07:25 +04:00
void
2013-03-01 12:38:47 +04:00
AndroidBridge : : CreateMessageList ( const dom : : mobilemessage : : SmsFilterData & aFilter , bool aReverse ,
2013-03-09 11:22:02 +04:00
nsIMobileMessageCallback * aRequest )
2011-12-20 12:07:25 +04:00
{
ALOG_BRIDGE ( " AndroidBridge::CreateMessageList " ) ;
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2013-01-25 23:00:00 +04:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-07 01:32:07 +04:00
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 2 ) ;
2011-12-20 12:07:25 +04:00
jobjectArray numbers =
2012-05-04 19:08:45 +04:00
( jobjectArray ) env - > NewObjectArray ( aFilter . numbers ( ) . Length ( ) ,
2012-07-02 23:32:34 +04:00
jStringClass ,
2012-12-14 02:03:44 +04:00
NewJavaString ( & jniFrame , EmptyString ( ) ) ) ;
2011-12-20 12:07:25 +04:00
2013-09-09 16:57:37 +04:00
for ( uint32_t i = 0 ; i < aFilter . numbers ( ) . Length ( ) ; + + i ) {
2014-01-06 21:54:22 +04:00
jstring elem = NewJavaString ( & jniFrame , aFilter . numbers ( ) [ i ] ) ;
env - > SetObjectArrayElement ( numbers , i , elem ) ;
env - > DeleteLocalRef ( elem ) ;
2013-09-09 16:57:37 +04:00
}
2012-11-07 01:32:07 +04:00
2013-11-12 22:41:01 +04:00
GeckoAppShell : : CreateMessageListWrapper ( aFilter . startDate ( ) , aFilter . endDate ( ) ,
2013-09-09 16:57:37 +04:00
numbers , aFilter . numbers ( ) . Length ( ) ,
aFilter . delivery ( ) , aReverse , requestId ) ;
2011-12-23 02:16:59 +04:00
}
2012-01-17 22:43:08 +04:00
void
2013-09-09 16:57:37 +04:00
AndroidBridge : : GetNextMessageInList ( int32_t aListId , nsIMobileMessageCallback * aRequest )
2012-01-17 22:43:08 +04:00
{
2013-09-09 16:57:37 +04:00
ALOG_BRIDGE ( " AndroidBridge::GetNextMessageInList " ) ;
2012-01-17 22:43:08 +04:00
2013-09-09 16:57:37 +04:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
2012-01-30 00:39:30 +04:00
return ;
2013-11-12 22:41:01 +04:00
GeckoAppShell : : GetNextMessageInListWrapper ( aListId , requestId ) ;
2012-01-17 22:43:08 +04:00
}
2013-01-25 23:00:00 +04:00
bool
2013-03-09 11:22:02 +04:00
AndroidBridge : : QueueSmsRequest ( nsIMobileMessageCallback * aRequest , uint32_t * aRequestIdOut )
2012-11-07 01:32:07 +04:00
{
2013-01-25 23:00:00 +04:00
MOZ_ASSERT ( NS_IsMainThread ( ) , " Wrong thread! " ) ;
MOZ_ASSERT ( aRequest & & aRequestIdOut ) ;
2012-11-08 20:37:13 +04:00
2013-04-08 18:29:34 +04:00
const uint32_t length = mSmsRequests . Length ( ) ;
2013-01-25 23:00:00 +04:00
for ( uint32_t i = 0 ; i < length ; i + + ) {
2013-04-08 18:29:34 +04:00
if ( ! ( mSmsRequests ) [ i ] ) {
( mSmsRequests ) [ i ] = aRequest ;
2013-01-25 23:00:00 +04:00
* aRequestIdOut = i ;
return true ;
2012-11-07 01:32:07 +04:00
}
}
2013-04-08 18:29:34 +04:00
mSmsRequests . AppendElement ( aRequest ) ;
2012-11-07 01:32:07 +04:00
2013-01-25 23:00:00 +04:00
// After AppendElement(), previous `length` points to the new tail element.
* aRequestIdOut = length ;
return true ;
2012-11-07 01:32:07 +04:00
}
2013-03-09 11:22:02 +04:00
already_AddRefed < nsIMobileMessageCallback >
2013-01-25 23:00:00 +04:00
AndroidBridge : : DequeueSmsRequest ( uint32_t aRequestId )
2012-11-07 01:32:07 +04:00
{
2013-01-25 23:00:00 +04:00
MOZ_ASSERT ( NS_IsMainThread ( ) , " Wrong thread! " ) ;
2013-04-08 18:29:34 +04:00
MOZ_ASSERT ( aRequestId < mSmsRequests . Length ( ) ) ;
if ( aRequestId > = mSmsRequests . Length ( ) ) {
2012-11-07 01:32:07 +04:00
return nullptr ;
}
2013-04-08 18:29:34 +04:00
return mSmsRequests [ aRequestId ] . forget ( ) ;
2012-11-07 01:32:07 +04:00
}
2012-01-16 17:44:07 +04:00
void
AndroidBridge : : GetCurrentNetworkInformation ( hal : : NetworkInformation * aNetworkInfo )
{
ALOG_BRIDGE ( " AndroidBridge::GetCurrentNetworkInformation " ) ;
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2012-01-16 17:44:07 +04:00
// To prevent calling too many methods through JNI, the Java method returns
2013-07-11 19:39:36 +04:00
// an array of double even if we actually want a double, two booleans, and an integer.
2012-05-04 19:08:47 +04:00
2013-11-12 22:41:01 +04:00
jdoubleArray arr = GeckoAppShell : : GetCurrentNetworkInformationWrapper ( ) ;
2013-07-11 19:39:36 +04:00
if ( ! arr | | env - > GetArrayLength ( arr ) ! = 4 ) {
2012-01-16 17:44:07 +04:00
return ;
}
2012-01-30 00:39:30 +04:00
jdouble * info = env - > GetDoubleArrayElements ( arr , 0 ) ;
2012-01-16 17:44:07 +04:00
aNetworkInfo - > bandwidth ( ) = info [ 0 ] ;
aNetworkInfo - > canBeMetered ( ) = info [ 1 ] = = 1.0f ;
2013-07-11 19:39:36 +04:00
aNetworkInfo - > isWifi ( ) = info [ 2 ] = = 1.0f ;
aNetworkInfo - > dhcpGateway ( ) = info [ 3 ] ;
2012-01-16 17:44:07 +04:00
2012-01-30 00:39:30 +04:00
env - > ReleaseDoubleArrayElements ( arr , info , 0 ) ;
2012-01-16 17:44:07 +04:00
}
2011-06-16 13:03:00 +04:00
void *
AndroidBridge : : LockBitmap ( jobject bitmap )
{
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
2012-05-04 19:08:47 +04:00
int err ;
void * buf ;
2012-01-30 00:39:30 +04:00
if ( ( err = AndroidBitmap_lockPixels ( env , bitmap , & buf ) ) ! = 0 ) {
2011-06-16 13:03:00 +04:00
ALOG_BRIDGE ( " AndroidBitmap_lockPixels failed! (error %d) " , err ) ;
2012-07-30 18:20:58 +04:00
buf = nullptr ;
2011-06-16 13:03:00 +04:00
}
return buf ;
}
void
AndroidBridge : : UnlockBitmap ( jobject bitmap )
{
2012-01-30 00:39:30 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
2012-05-04 19:08:47 +04:00
int err ;
2012-01-30 00:39:30 +04:00
if ( ( err = AndroidBitmap_unlockPixels ( env , bitmap ) ) ! = 0 )
2011-06-16 13:03:00 +04:00
ALOG_BRIDGE ( " AndroidBitmap_unlockPixels failed! (error %d) " , err ) ;
}
2011-09-21 20:46:00 +04:00
bool
AndroidBridge : : HasNativeWindowAccess ( )
{
OpenGraphicsLibraries ( ) ;
2012-04-28 00:04:47 +04:00
// We have a fallback hack in place, so return true if that will work as well
return mHasNativeWindowAccess | | mHasNativeWindowFallback ;
2011-09-21 20:46:00 +04:00
}
void *
2012-04-28 00:04:47 +04:00
AndroidBridge : : AcquireNativeWindow ( JNIEnv * aEnv , jobject aSurface )
2011-09-21 20:46:00 +04:00
{
2012-04-28 00:04:47 +04:00
OpenGraphicsLibraries ( ) ;
2011-09-21 20:46:00 +04:00
2012-04-28 00:04:47 +04:00
if ( mHasNativeWindowAccess )
return ANativeWindow_fromSurface ( aEnv , aSurface ) ;
2012-07-20 23:20:51 +04:00
if ( mHasNativeWindowFallback )
2012-04-28 00:04:47 +04:00
return GetNativeSurface ( aEnv , aSurface ) ;
2012-07-20 23:20:51 +04:00
2012-07-30 18:20:58 +04:00
return nullptr ;
2011-09-21 20:46:00 +04:00
}
void
AndroidBridge : : ReleaseNativeWindow ( void * window )
{
if ( ! window )
return ;
2012-04-28 00:04:47 +04:00
if ( mHasNativeWindowAccess )
ANativeWindow_release ( window ) ;
// XXX: we don't ref the pointer we get from the fallback (GetNativeSurface), so we
// have nothing to do here. We should probably ref it.
2011-09-21 20:46:00 +04:00
}
2012-07-20 23:20:51 +04:00
void *
AndroidBridge : : AcquireNativeWindowFromSurfaceTexture ( JNIEnv * aEnv , jobject aSurfaceTexture )
{
OpenGraphicsLibraries ( ) ;
if ( mHasNativeWindowAccess & & ANativeWindow_fromSurfaceTexture )
return ANativeWindow_fromSurfaceTexture ( aEnv , aSurfaceTexture ) ;
if ( mHasNativeWindowAccess & & android_SurfaceTexture_getNativeWindow ) {
android : : sp < AndroidRefable > window = android_SurfaceTexture_getNativeWindow ( aEnv , aSurfaceTexture ) ;
return window . get ( ) ;
}
2012-07-30 18:20:58 +04:00
return nullptr ;
2012-07-20 23:20:51 +04:00
}
void
AndroidBridge : : ReleaseNativeWindowForSurfaceTexture ( void * window )
{
if ( ! window )
return ;
// FIXME: we don't ref the pointer we get, so nothing to do currently. We should ref it.
}
2011-09-21 20:46:00 +04:00
bool
AndroidBridge : : LockWindow ( void * window , unsigned char * * bits , int * width , int * height , int * format , int * stride )
{
/* Copied from native_window.h in Android NDK (platform-9) */
typedef struct ANativeWindow_Buffer {
// The number of pixels that are show horizontally.
int32_t width ;
// The number of pixels that are shown vertically.
int32_t height ;
// The number of *pixels* that a line in the buffer takes in
// memory. This may be >= width.
int32_t stride ;
// The format of the buffer. One of WINDOW_FORMAT_*
int32_t format ;
// The actual bits.
void * bits ;
// Do not touch.
uint32_t reserved [ 6 ] ;
} ANativeWindow_Buffer ;
2012-04-28 00:04:47 +04:00
// Very similar to the above, but the 'usage' field is included. We use this
// in the fallback case when NDK support is not available
2012-07-12 20:52:52 +04:00
struct SurfaceInfo {
2012-04-28 00:04:47 +04:00
uint32_t w ;
uint32_t h ;
uint32_t s ;
uint32_t usage ;
uint32_t format ;
unsigned char * bits ;
uint32_t reserved [ 2 ] ;
} ;
2011-09-21 20:46:00 +04:00
2012-04-28 00:04:47 +04:00
int err ;
2013-10-11 00:42:52 +04:00
* bits = nullptr ;
2011-09-21 20:46:00 +04:00
* width = * height = * format = 0 ;
2012-07-02 23:32:34 +04:00
2012-04-28 00:04:47 +04:00
if ( mHasNativeWindowAccess ) {
ANativeWindow_Buffer buffer ;
2011-09-21 20:46:00 +04:00
2013-10-11 00:42:52 +04:00
if ( ( err = ANativeWindow_lock ( window , ( void * ) & buffer , nullptr ) ) ! = 0 ) {
2012-04-28 00:04:47 +04:00
ALOG_BRIDGE ( " ANativeWindow_lock failed! (error %d) " , err ) ;
return false ;
}
* bits = ( unsigned char * ) buffer . bits ;
* width = buffer . width ;
* height = buffer . height ;
* format = buffer . format ;
* stride = buffer . stride ;
} else if ( mHasNativeWindowFallback ) {
SurfaceInfo info ;
2013-10-11 00:42:52 +04:00
if ( ( err = Surface_lock ( window , & info , nullptr , true ) ) ! = 0 ) {
2012-04-28 00:04:47 +04:00
ALOG_BRIDGE ( " Surface_lock failed! (error %d) " , err ) ;
return false ;
}
* bits = info . bits ;
* width = info . w ;
* height = info . h ;
* format = info . format ;
* stride = info . s ;
} else return false ;
2011-09-21 20:46:00 +04:00
return true ;
}
2013-05-28 20:49:04 +04:00
jobject
AndroidBridge : : GetGlobalContextRef ( ) {
2013-09-25 10:06:21 +04:00
if ( sGlobalContext = = nullptr ) {
JNIEnv * env = GetJNIForThread ( ) ;
2013-05-28 20:49:04 +04:00
2013-09-25 10:06:21 +04:00
AutoLocalJNIFrame jniFrame ( env , 4 ) ;
2013-05-28 20:49:04 +04:00
2013-11-12 22:41:01 +04:00
jobject context = GeckoAppShell : : GetContext ( ) ;
2013-09-25 10:06:21 +04:00
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 ;
}
2013-05-28 20:49:04 +04:00
2013-09-25 10:06:21 +04:00
sGlobalContext = env - > NewGlobalRef ( appContext ) ;
MOZ_ASSERT ( sGlobalContext ) ;
}
2013-02-10 01:38:08 +04:00
2013-09-25 10:06:21 +04:00
return sGlobalContext ;
2013-02-10 01:38:08 +04:00
}
2011-09-21 20:46:00 +04:00
bool
AndroidBridge : : UnlockWindow ( void * window )
{
int err ;
2012-04-28 00:04:47 +04:00
if ( ! HasNativeWindowAccess ( ) )
return false ;
if ( mHasNativeWindowAccess & & ( err = ANativeWindow_unlockAndPost ( window ) ) ! = 0 ) {
2011-09-21 20:46:00 +04:00
ALOG_BRIDGE ( " ANativeWindow_unlockAndPost failed! (error %d) " , err ) ;
return false ;
2012-04-28 00:04:47 +04:00
} else if ( mHasNativeWindowFallback & & ( err = Surface_unlockAndPost ( window ) ) ! = 0 ) {
ALOG_BRIDGE ( " Surface_unlockAndPost failed! (error %d) " , err ) ;
return false ;
2011-09-21 20:46:00 +04:00
}
return true ;
}
2011-10-11 04:40:17 +04:00
2012-03-12 19:50:21 +04:00
void
2013-06-22 01:03:56 +04:00
AndroidBridge : : SetFirstPaintViewport ( const LayerIntPoint & aOffset , const CSSToLayerScale & aZoom , const CSSRect & aCssPageRect )
2012-03-12 19:50:21 +04:00
{
2013-11-12 22:41:01 +04:00
GeckoLayerClient * client = mLayerClient ;
2012-03-12 19:50:21 +04:00
if ( ! client )
return ;
2013-11-12 22:41:01 +04:00
client - > SetFirstPaintViewport ( ( float ) aOffset . x , ( float ) aOffset . y , aZoom . scale ,
aCssPageRect . x , aCssPageRect . y , aCssPageRect . XMost ( ) , aCssPageRect . YMost ( ) ) ;
2012-03-12 19:50:21 +04:00
}
void
2013-06-03 17:52:44 +04:00
AndroidBridge : : SetPageRect ( const CSSRect & aCssPageRect )
2012-03-12 19:50:21 +04:00
{
2013-11-12 22:41:01 +04:00
GeckoLayerClient * client = mLayerClient ;
2012-03-12 19:50:21 +04:00
if ( ! client )
return ;
2013-11-12 22:41:01 +04:00
client - > SetPageRect ( aCssPageRect . x , aCssPageRect . y , aCssPageRect . XMost ( ) , aCssPageRect . YMost ( ) ) ;
2012-03-12 19:50:21 +04:00
}
2012-02-04 06:35:58 +04:00
void
2013-06-22 01:03:56 +04:00
AndroidBridge : : SyncViewportInfo ( const LayerIntRect & aDisplayPort , const CSSToLayerScale & aDisplayResolution ,
bool aLayersUpdated , ScreenPoint & aScrollOffset , CSSToScreenScale & aScale ,
2013-07-22 12:50:13 +04:00
LayerMargin & aFixedLayerMargins , ScreenPoint & aOffset )
2012-02-04 06:35:58 +04:00
{
2013-11-12 22:41:01 +04:00
GeckoLayerClient * client = mLayerClient ;
if ( ! client ) {
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! " ) ;
if ( ! viewTransformJObj ) {
2012-03-14 08:15:11 +04:00
return ;
2013-11-12 22:41:01 +04:00
}
2012-03-14 08:15:11 +04:00
2013-11-12 22:41:01 +04:00
ViewTransform * viewTransform = ViewTransform : : Wrap ( viewTransformJObj ) ;
aScrollOffset = ScreenPoint ( 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 ;
2012-02-04 06:35:58 +04:00
}
2013-06-15 00:11:29 +04:00
void AndroidBridge : : SyncFrameMetrics ( const ScreenPoint & aScrollOffset , float aZoom , const CSSRect & aCssPageRect ,
2013-06-22 01:03:56 +04:00
bool aLayersUpdated , const CSSRect & aDisplayPort , const CSSToLayerScale & aDisplayResolution ,
2013-07-22 12:50:13 +04:00
bool aIsFirstPaint , LayerMargin & aFixedLayerMargins , ScreenPoint & aOffset )
2013-04-26 21:26:39 +04:00
{
2013-11-12 22:41:01 +04:00
GeckoLayerClient * client = mLayerClient ;
if ( ! client ) {
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
2013-04-26 21:26:39 +04:00
return ;
2013-11-12 22:41:01 +04:00
}
2013-04-26 21:26:39 +04:00
2013-11-12 22:41:01 +04:00
// convert the displayport rect from scroll-relative CSS pixels to document-relative device pixels
LayerRect dpUnrounded = aDisplayPort * aDisplayResolution ;
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 ) ;
NS_ABORT_IF_FALSE ( viewTransformJObj , " No view transform object! " ) ;
if ( ! viewTransformJObj ) {
return ;
}
ViewTransform * viewTransform = ViewTransform : : Wrap ( viewTransformJObj ) ;
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 ;
2013-04-26 21:26:39 +04:00
}
2012-07-14 01:34:58 +04:00
AndroidBridge : : AndroidBridge ( )
2013-10-11 00:42:52 +04:00
: mLayerClient ( nullptr ) ,
mNativePanZoomController ( nullptr )
2012-07-14 01:34:58 +04:00
{
}
AndroidBridge : : ~ AndroidBridge ( )
{
}
2011-10-11 04:40:17 +04:00
/* Implementation file */
NS_IMPL_ISUPPORTS1 ( nsAndroidBridge , nsIAndroidBridge )
nsAndroidBridge : : nsAndroidBridge ( )
{
}
nsAndroidBridge : : ~ nsAndroidBridge ( )
{
}
/* void handleGeckoEvent (in AString message); */
2012-07-07 00:14:07 +04:00
NS_IMETHODIMP nsAndroidBridge : : HandleGeckoMessage ( const nsAString & message , nsAString & aRet )
2011-10-11 04:40:17 +04:00
{
2011-10-24 21:05:18 +04:00
AndroidBridge : : Bridge ( ) - > HandleGeckoMessage ( message , aRet ) ;
2011-10-11 04:40:17 +04:00
return NS_OK ;
}
2011-11-18 07:20:29 +04:00
2013-05-30 17:55:08 +04:00
/* nsIAndroidDisplayport getDisplayPort(in boolean aPageSizeUpdate, in boolean isBrowserContentDisplayed, in int32_t tabId, in nsIAndroidViewport metrics); */
NS_IMETHODIMP nsAndroidBridge : : GetDisplayPort ( bool aPageSizeUpdate , bool aIsBrowserContentDisplayed , int32_t tabId , nsIAndroidViewport * metrics , nsIAndroidDisplayport * * displayPort )
{
AndroidBridge : : Bridge ( ) - > GetDisplayPort ( aPageSizeUpdate , aIsBrowserContentDisplayed , tabId , metrics , displayPort ) ;
return NS_OK ;
}
2013-05-30 17:55:23 +04:00
/* void displayedDocumentChanged(); */
NS_IMETHODIMP nsAndroidBridge : : ContentDocumentChanged ( )
{
AndroidBridge : : Bridge ( ) - > ContentDocumentChanged ( ) ;
return NS_OK ;
}
/* boolean isContentDocumentDisplayed(); */
NS_IMETHODIMP nsAndroidBridge : : IsContentDocumentDisplayed ( bool * aRet )
{
* aRet = AndroidBridge : : Bridge ( ) - > IsContentDocumentDisplayed ( ) ;
return NS_OK ;
}
2012-01-30 00:39:30 +04:00
// DO NOT USE THIS unless you need to access JNI from
// non-main threads. This is probably not what you want.
// Questions, ask blassey or dougt.
static void
JavaThreadDetachFunc ( void * arg )
{
JNIEnv * env = ( JNIEnv * ) arg ;
2013-10-11 00:42:52 +04:00
JavaVM * vm = nullptr ;
2012-01-30 00:39:30 +04:00
env - > GetJavaVM ( & vm ) ;
vm - > DetachCurrentThread ( ) ;
}
2012-05-09 01:36:07 +04:00
uint32_t
AndroidBridge : : GetScreenOrientation ( )
2012-03-20 17:09:45 +04:00
{
ALOG_BRIDGE ( " AndroidBridge::GetScreenOrientation " ) ;
2012-05-04 19:08:47 +04:00
2013-11-12 22:41:01 +04:00
int16_t orientation = GeckoAppShell : : GetScreenOrientationWrapper ( ) ;
2012-05-04 19:08:47 +04:00
2013-09-09 16:57:37 +04:00
if ( ! orientation )
2012-05-09 01:36:07 +04:00
return dom : : eScreenOrientation_None ;
2012-05-04 19:08:47 +04:00
2012-05-09 01:36:07 +04:00
return static_cast < dom : : ScreenOrientation > ( orientation ) ;
2012-03-20 17:09:45 +04:00
}
2012-07-20 23:20:51 +04:00
void
AndroidBridge : : ScheduleComposite ( )
{
nsWindow : : ScheduleComposite ( ) ;
}
2012-11-13 23:25:18 +04:00
nsresult
AndroidBridge : : GetProxyForURI ( const nsACString & aSpec ,
const nsACString & aScheme ,
const nsACString & aHost ,
const int32_t aPort ,
nsACString & aResult )
{
2014-01-18 09:32:24 +04:00
if ( ! HasEnv ( ) ) {
return NS_ERROR_FAILURE ;
}
2012-11-13 23:25:18 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 22:41:01 +04:00
jstring jstrRet = GeckoAppShell : : GetProxyForURIWrapper ( NS_ConvertUTF8toUTF16 ( aSpec ) ,
2013-09-09 16:57:37 +04:00
NS_ConvertUTF8toUTF16 ( aScheme ) ,
NS_ConvertUTF8toUTF16 ( aHost ) ,
aPort ) ;
2012-11-13 23:25:18 +04:00
2013-09-09 16:57:37 +04:00
if ( ! jstrRet )
2012-11-13 23:25:18 +04:00
return NS_ERROR_FAILURE ;
nsJNIString jniStr ( jstrRet , env ) ;
CopyUTF16toUTF8 ( jniStr , aResult ) ;
return NS_OK ;
}
2012-02-17 22:52:26 +04:00
/* attribute nsIAndroidBrowserApp browserApp; */
NS_IMETHODIMP nsAndroidBridge : : GetBrowserApp ( nsIAndroidBrowserApp * * aBrowserApp )
{
if ( nsAppShell : : gAppShell )
nsAppShell : : gAppShell - > GetBrowserApp ( aBrowserApp ) ;
return NS_OK ;
}
2012-05-04 19:08:47 +04:00
2012-02-17 22:52:26 +04:00
NS_IMETHODIMP nsAndroidBridge : : SetBrowserApp ( nsIAndroidBrowserApp * aBrowserApp )
{
if ( nsAppShell : : gAppShell )
nsAppShell : : gAppShell - > SetBrowserApp ( aBrowserApp ) ;
return NS_OK ;
}
2012-03-27 09:31:57 +04:00
void
2013-08-13 19:49:21 +04:00
AndroidBridge : : AddPluginView ( jobject view , const LayoutDeviceRect & rect , bool isFullScreen ) {
nsWindow * win = nsWindow : : TopWindow ( ) ;
if ( ! win )
return ;
2013-09-18 04:45:19 +04:00
CSSRect cssRect = rect / win - > GetDefaultScale ( ) ;
2013-11-12 22:41:01 +04:00
GeckoAppShell : : AddPluginViewWrapper ( view , cssRect . x , cssRect . y , cssRect . width , cssRect . height , isFullScreen ) ;
2012-03-27 09:31:57 +04:00
}
2012-02-17 22:52:26 +04:00
extern " C "
__attribute__ ( ( visibility ( " default " ) ) )
jobject JNICALL
2012-05-04 19:08:47 +04:00
Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer ( JNIEnv * env , jclass , jlong size ) ;
2012-02-17 22:52:26 +04:00
2013-04-23 21:10:29 +04:00
bool
AndroidBridge : : GetThreadNameJavaProfiling ( uint32_t aThreadId , nsCString & aResult )
{
JNIEnv * env = GetJNIForThread ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-04-23 21:10:29 +04:00
2013-11-12 22:41:01 +04:00
jstring jstrThreadName = GeckoJavaSampler : : GetThreadNameJavaProfilingWrapper ( aThreadId ) ;
2013-04-23 21:10:29 +04:00
if ( ! jstrThreadName )
return false ;
nsJNIString jniStr ( jstrThreadName , env ) ;
CopyUTF16toUTF8 ( jniStr . get ( ) , aResult ) ;
return true ;
}
bool
AndroidBridge : : GetFrameNameJavaProfiling ( uint32_t aThreadId , uint32_t aSampleId ,
uint32_t aFrameId , nsCString & aResult )
{
JNIEnv * env = GetJNIForThread ( ) ;
2014-01-06 21:54:22 +04:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-04-23 21:10:29 +04:00
2013-11-12 22:41:01 +04:00
jstring jstrSampleName = GeckoJavaSampler : : GetFrameNameJavaProfilingWrapper ( aThreadId , aSampleId , aFrameId ) ;
2013-04-23 21:10:29 +04:00
if ( ! jstrSampleName )
return false ;
nsJNIString jniStr ( jstrSampleName , env ) ;
CopyUTF16toUTF8 ( jniStr . get ( ) , aResult ) ;
return true ;
}
2012-12-15 19:43:52 +04:00
nsresult AndroidBridge : : CaptureThumbnail ( nsIDOMWindow * window , int32_t bufW , int32_t bufH , int32_t tabId , jobject buffer )
2012-02-04 10:48:26 +04:00
{
2012-05-04 03:29:59 +04:00
nsresult rv ;
2012-06-14 20:08:51 +04:00
float scale = 1.0 ;
2012-07-02 23:32:34 +04:00
2012-06-14 20:08:51 +04:00
if ( ! buffer )
2013-01-23 21:18:05 +04:00
return NS_ERROR_FAILURE ;
2012-05-04 03:29:59 +04:00
// take a screenshot, as wide as possible, proportional to the destination size
2012-12-15 19:43:52 +04:00
nsCOMPtr < nsIDOMWindowUtils > utils = do_GetInterface ( window ) ;
if ( ! utils )
return NS_ERROR_FAILURE ;
nsCOMPtr < nsIDOMClientRect > rect ;
rv = utils - > GetRootBounds ( getter_AddRefs ( rect ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
if ( ! rect )
return NS_ERROR_FAILURE ;
2012-06-02 07:50:57 +04:00
2012-12-15 19:43:52 +04:00
float left , top , width , height ;
rect - > GetLeft ( & left ) ;
rect - > GetTop ( & top ) ;
rect - > GetWidth ( & width ) ;
rect - > GetHeight ( & height ) ;
if ( width = = 0 | | height = = 0 )
return NS_ERROR_FAILURE ;
int32_t srcX = left ;
int32_t srcY = top ;
int32_t srcW ;
int32_t srcH ;
float aspectRatio = ( ( float ) bufW ) / bufH ;
if ( width / aspectRatio < height ) {
srcW = width ;
srcH = width / aspectRatio ;
} else {
srcW = height * aspectRatio ;
srcH = height ;
2012-05-04 03:29:59 +04:00
}
2012-05-04 19:08:47 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2013-01-23 21:18:05 +04:00
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
2012-05-04 19:08:47 +04:00
2012-02-04 10:48:26 +04:00
nsCOMPtr < nsPIDOMWindow > win = do_QueryInterface ( window ) ;
if ( ! win )
return NS_ERROR_FAILURE ;
nsRefPtr < nsPresContext > presContext ;
nsIDocShell * docshell = win - > GetDocShell ( ) ;
if ( docshell ) {
docshell - > GetPresContext ( getter_AddRefs ( presContext ) ) ;
}
if ( ! presContext )
return NS_ERROR_FAILURE ;
nscolor bgColor = NS_RGB ( 255 , 255 , 255 ) ;
2012-10-27 05:02:57 +04:00
nsCOMPtr < nsIPresShell > presShell = presContext - > PresShell ( ) ;
2012-08-22 19:56:38 +04:00
uint32_t renderDocFlags = ( nsIPresShell : : RENDER_IGNORE_VIEWPORT_SCROLLING |
2012-02-04 10:48:26 +04:00
nsIPresShell : : RENDER_DOCUMENT_RELATIVE ) ;
2012-03-15 08:43:53 +04:00
nsRect r ( nsPresContext : : CSSPixelsToAppUnits ( srcX / scale ) ,
nsPresContext : : CSSPixelsToAppUnits ( srcY / scale ) ,
nsPresContext : : CSSPixelsToAppUnits ( srcW / scale ) ,
nsPresContext : : CSSPixelsToAppUnits ( srcH / scale ) ) ;
2012-02-04 10:48:26 +04:00
2013-07-04 17:53:25 +04:00
bool is24bit = ( GetScreenDepth ( ) = = 24 ) ;
uint32_t stride = bufW * ( is24bit ? 4 : 2 ) ;
2012-02-17 22:52:26 +04:00
2012-05-04 19:08:47 +04:00
void * data = env - > GetDirectBufferAddress ( buffer ) ;
2012-09-25 23:46:17 +04:00
if ( ! data )
return NS_ERROR_FAILURE ;
2013-07-04 17:53:25 +04:00
nsRefPtr < gfxImageSurface > surf =
new gfxImageSurface ( static_cast < unsigned char * > ( data ) , nsIntSize ( bufW , bufH ) , stride ,
2013-09-25 00:45:13 +04:00
is24bit ? gfxImageFormatRGB24 :
gfxImageFormatRGB16_565 ) ;
2012-08-14 04:01:31 +04:00
if ( surf - > CairoStatus ( ) ! = 0 ) {
ALOG_BRIDGE ( " Error creating gfxImageSurface " ) ;
return NS_ERROR_FAILURE ;
}
2013-10-15 07:23:20 +04:00
nsRefPtr < gfxContext > context ;
2014-01-10 23:06:16 +04:00
if ( gfxPlatform : : GetPlatform ( ) - > SupportsAzureContentForType ( BackendType : : CAIRO ) ) {
2013-10-15 07:23:20 +04:00
RefPtr < DrawTarget > dt =
gfxPlatform : : GetPlatform ( ) - > CreateDrawTargetForSurface ( surf , IntSize ( bufW , bufH ) ) ;
if ( ! dt ) {
ALOG_BRIDGE ( " Error creating DrawTarget " ) ;
return NS_ERROR_FAILURE ;
}
context = new gfxContext ( dt ) ;
} else {
context = new gfxContext ( surf ) ;
}
2012-12-15 19:43:52 +04:00
gfxPoint pt ( 0 , 0 ) ;
2012-06-14 20:08:51 +04:00
context - > Translate ( pt ) ;
2012-12-15 19:43:52 +04:00
context - > Scale ( scale * bufW / srcW , scale * bufH / srcH ) ;
2012-05-04 03:29:59 +04:00
rv = presShell - > RenderDocument ( r , renderDocFlags , bgColor , context ) ;
2013-07-24 17:18:05 +04:00
if ( is24bit ) {
gfxUtils : : ConvertBGRAtoRGBA ( surf ) ;
}
2012-02-04 10:48:26 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
return NS_OK ;
}
2012-04-24 23:13:36 +04:00
2013-05-30 17:55:08 +04:00
void
2012-09-13 01:47:08 +04:00
AndroidBridge : : GetDisplayPort ( bool aPageSizeUpdate , bool aIsBrowserContentDisplayed , int32_t tabId , nsIAndroidViewport * metrics , nsIAndroidDisplayport * * displayPort )
{
2013-11-12 22:41:01 +04:00
ALOG_BRIDGE ( " Enter: %s " , __PRETTY_FUNCTION__ ) ;
2012-09-13 01:47:08 +04:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-18 09:32:24 +04:00
if ( ! mLayerClient | | mLayerClient - > isNull ( ) ) {
2013-11-12 22:41:01 +04:00
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
2013-05-30 17:55:08 +04:00
return ;
2013-11-12 22:41:01 +04:00
}
2012-09-13 01:47:08 +04:00
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
2013-11-12 22:41:01 +04:00
float x , y , width , height ,
pageLeft , pageTop , pageRight , pageBottom ,
cssPageLeft , cssPageTop , cssPageRight , cssPageBottom ,
zoom ;
metrics - > GetX ( & x ) ;
metrics - > GetY ( & y ) ;
metrics - > GetWidth ( & width ) ;
metrics - > GetHeight ( & height ) ;
metrics - > GetPageLeft ( & pageLeft ) ;
metrics - > GetPageTop ( & pageTop ) ;
metrics - > GetPageRight ( & pageRight ) ;
metrics - > GetPageBottom ( & pageBottom ) ;
metrics - > GetCssPageLeft ( & cssPageLeft ) ;
metrics - > GetCssPageTop ( & cssPageTop ) ;
metrics - > GetCssPageRight ( & cssPageRight ) ;
metrics - > GetCssPageBottom ( & cssPageBottom ) ;
metrics - > GetZoom ( & zoom ) ;
ImmutableViewportMetrics jmetrics = ImmutableViewportMetrics ( 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 ) ;
AndroidRectF rect ( env , displayPortMetrics - > getMPosition ( ) ) ;
if ( jniFrame . CheckForException ( ) ) {
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
return ;
}
float resolution = displayPortMetrics - > getResolution ( ) ;
if ( jniFrame . CheckForException ( ) ) {
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
return ;
}
* displayPort = new nsAndroidDisplayport ( rect , resolution ) ;
( * displayPort ) - > AddRef ( ) ;
delete displayPortMetrics ;
ALOG_BRIDGE ( " Exit: %s " , __PRETTY_FUNCTION__ ) ;
2012-09-13 01:47:08 +04:00
}
2013-05-30 17:55:23 +04:00
void
AndroidBridge : : ContentDocumentChanged ( )
{
2013-11-12 22:41:01 +04:00
if ( ! mLayerClient ) {
2013-05-30 17:55:23 +04:00
return ;
2013-11-12 22:41:01 +04:00
}
mLayerClient - > ContentDocumentChanged ( ) ;
2013-05-30 17:55:23 +04:00
}
bool
AndroidBridge : : IsContentDocumentDisplayed ( )
{
2014-01-18 09:32:24 +04:00
if ( ! mLayerClient )
2013-05-30 17:55:23 +04:00
return false ;
2013-11-12 22:41:01 +04:00
return mLayerClient - > IsContentDocumentDisplayed ( ) ;
2013-05-30 17:55:23 +04:00
}
2012-10-04 22:45:16 +04:00
bool
2013-11-27 21:33:27 +04:00
AndroidBridge : : ProgressiveUpdateCallback ( bool aHasPendingNewThebesContent , const LayerRect & aDisplayPort , float aDisplayResolution , bool aDrawingCritical , ScreenRect & aCompositionBounds , CSSToScreenScale & aZoom )
2012-10-04 22:45:16 +04:00
{
2013-11-12 22:41:01 +04:00
GeckoLayerClient * client = mLayerClient ;
if ( ! client ) {
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
2012-10-04 22:45:16 +04:00
return false ;
2013-11-12 22:41:01 +04:00
}
jobject progressiveUpdateDataJObj = client - > 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! " ) ;
ProgressiveUpdateData * progressiveUpdateData = ProgressiveUpdateData : : Wrap ( progressiveUpdateDataJObj ) ;
2012-10-04 22:45:16 +04:00
2013-11-27 21:33:27 +04:00
aCompositionBounds . x = progressiveUpdateData - > getx ( ) ;
aCompositionBounds . y = progressiveUpdateData - > gety ( ) ;
aCompositionBounds . width = progressiveUpdateData - > getwidth ( ) ;
aCompositionBounds . height = progressiveUpdateData - > getheight ( ) ;
aZoom . scale = progressiveUpdateData - > getscale ( ) ;
2013-11-12 22:41:01 +04:00
bool ret = progressiveUpdateData - > getabort ( ) ;
delete progressiveUpdateData ;
return ret ;
2012-10-04 22:45:16 +04:00
}
2013-11-12 22:41:01 +04:00
NativePanZoomController *
2013-04-26 21:24:28 +04:00
AndroidBridge : : SetNativePanZoomController ( jobject obj )
{
2013-11-12 22:41:01 +04:00
NativePanZoomController * old = mNativePanZoomController ;
mNativePanZoomController = NativePanZoomController : : Wrap ( obj ) ;
2013-04-26 21:24:28 +04:00
return old ;
}
void
AndroidBridge : : RequestContentRepaint ( const mozilla : : layers : : FrameMetrics & aFrameMetrics )
{
2013-04-26 21:26:46 +04:00
ALOG_BRIDGE ( " AndroidBridge::RequestContentRepaint " ) ;
2013-08-26 18:34:56 +04:00
CSSToScreenScale resolution = aFrameMetrics . mZoom ;
2013-06-15 00:11:44 +04:00
ScreenRect dp = ( aFrameMetrics . mDisplayPort + aFrameMetrics . mScrollOffset ) * resolution ;
2013-04-26 21:26:46 +04:00
2013-11-12 22:41:01 +04:00
mNativePanZoomController - > RequestContentRepaintWrapper ( dp . x , dp . y , dp . width , dp . height , resolution . scale ) ;
2013-04-26 21:24:28 +04:00
}
void
2013-11-26 08:30:26 +04:00
AndroidBridge : : HandleDoubleTap ( const CSSIntPoint & aPoint , int32_t aModifiers )
2013-04-26 21:24:28 +04:00
{
2013-04-26 21:26:46 +04:00
nsCString data = nsPrintfCString ( " { \" x \" : %d, \" y \" : %d } " , aPoint . x , aPoint . y ) ;
nsAppShell : : gAppShell - > PostEvent ( AndroidGeckoEvent : : MakeBroadcastEvent (
NS_LITERAL_CSTRING ( " Gesture:DoubleTap " ) , data ) ) ;
2013-04-26 21:24:28 +04:00
}
void
2013-11-26 08:30:26 +04:00
AndroidBridge : : HandleSingleTap ( const CSSIntPoint & aPoint , int32_t aModifiers )
2013-04-26 21:24:28 +04:00
{
2013-11-26 08:30:26 +04:00
// TODO Send the modifier data to Gecko for use in mouse events.
2013-04-26 21:26:46 +04:00
nsCString data = nsPrintfCString ( " { \" x \" : %d, \" y \" : %d } " , aPoint . x , aPoint . y ) ;
nsAppShell : : gAppShell - > PostEvent ( AndroidGeckoEvent : : MakeBroadcastEvent (
NS_LITERAL_CSTRING ( " Gesture:SingleTap " ) , data ) ) ;
2013-04-26 21:24:28 +04:00
}
void
2013-11-26 08:30:26 +04:00
AndroidBridge : : HandleLongTap ( const CSSIntPoint & aPoint , int32_t aModifiers )
2013-04-26 21:24:28 +04:00
{
2013-04-26 21:26:46 +04:00
nsCString data = nsPrintfCString ( " { \" x \" : %d, \" y \" : %d } " , aPoint . x , aPoint . y ) ;
nsAppShell : : gAppShell - > PostEvent ( AndroidGeckoEvent : : MakeBroadcastEvent (
NS_LITERAL_CSTRING ( " Gesture:LongPress " ) , data ) ) ;
2013-04-26 21:24:28 +04:00
}
2013-12-12 04:39:06 +04:00
void
AndroidBridge : : HandleLongTapUp ( const CSSIntPoint & aPoint , int32_t aModifiers )
{
}
2013-04-26 21:24:28 +04:00
void
2013-11-09 04:07:00 +04:00
AndroidBridge : : SendAsyncScrollDOMEvent ( bool aIsRoot ,
2013-07-30 22:03:42 +04:00
const CSSRect & aContentRect ,
const CSSSize & aScrollableSize )
2013-04-26 21:24:28 +04:00
{
// FIXME implement this
}
void
2013-04-26 21:26:46 +04:00
AndroidBridge : : PostDelayedTask ( Task * aTask , int aDelayMs )
2013-04-26 21:24:28 +04:00
{
2013-04-26 21:26:46 +04:00
// add the new task into the mDelayedTaskQueue, sorted with
// the earliest task first in the queue
DelayedTask * newTask = new DelayedTask ( aTask , aDelayMs ) ;
uint32_t i = 0 ;
while ( i < mDelayedTaskQueue . Length ( ) ) {
if ( newTask - > IsEarlierThan ( mDelayedTaskQueue [ i ] ) ) {
mDelayedTaskQueue . InsertElementAt ( i , newTask ) ;
break ;
}
i + + ;
}
if ( i = = mDelayedTaskQueue . Length ( ) ) {
// this new task will run after all the existing tasks in the queue
mDelayedTaskQueue . AppendElement ( newTask ) ;
}
if ( i = = 0 ) {
// if we're inserting it at the head of the queue, notify Java because
// we need to get a callback at an earlier time than the last scheduled
// callback
2013-11-12 22:41:01 +04:00
mNativePanZoomController - > PostDelayedCallbackWrapper ( ( int64_t ) aDelayMs ) ;
2013-04-26 21:26:46 +04:00
}
}
int64_t
AndroidBridge : : RunDelayedTasks ( )
{
while ( mDelayedTaskQueue . Length ( ) > 0 ) {
DelayedTask * nextTask = mDelayedTaskQueue [ 0 ] ;
int64_t timeLeft = nextTask - > MillisecondsToRunTime ( ) ;
if ( timeLeft > 0 ) {
// this task (and therefore all remaining tasks)
// have not yet reached their runtime. return the
// time left until we should be called again
return timeLeft ;
}
// we have a delayed task to run. extract it from
// the wrapper and free the wrapper
mDelayedTaskQueue . RemoveElementAt ( 0 ) ;
Task * task = nextTask - > GetTask ( ) ;
delete nextTask ;
task - > Run ( ) ;
}
return - 1 ;
2013-04-26 21:24:28 +04:00
}