1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/android/AndroidJNI.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1012 @@ 1.4 +/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "mozilla/Hal.h" 1.10 +#include "nsIFile.h" 1.11 +#include "nsString.h" 1.12 + 1.13 +#include "AndroidBridge.h" 1.14 +#include "AndroidGraphicBuffer.h" 1.15 + 1.16 +#include <jni.h> 1.17 +#include <pthread.h> 1.18 +#include <dlfcn.h> 1.19 +#include <stdio.h> 1.20 +#include <unistd.h> 1.21 +#include <sched.h> 1.22 + 1.23 +#include "nsAppShell.h" 1.24 +#include "nsWindow.h" 1.25 +#include <android/log.h> 1.26 +#include "nsIObserverService.h" 1.27 +#include "mozilla/Services.h" 1.28 +#include "nsThreadUtils.h" 1.29 + 1.30 +#ifdef MOZ_CRASHREPORTER 1.31 +#include "nsICrashReporter.h" 1.32 +#include "nsExceptionHandler.h" 1.33 +#endif 1.34 + 1.35 +#include "mozilla/unused.h" 1.36 + 1.37 +#include "mozilla/dom/SmsMessage.h" 1.38 +#include "mozilla/dom/mobilemessage/Constants.h" 1.39 +#include "mozilla/dom/mobilemessage/Types.h" 1.40 +#include "mozilla/dom/mobilemessage/PSms.h" 1.41 +#include "mozilla/dom/mobilemessage/SmsParent.h" 1.42 +#include "mozilla/layers/APZCTreeManager.h" 1.43 +#include "nsIMobileMessageDatabaseService.h" 1.44 +#include "nsPluginInstanceOwner.h" 1.45 +#include "nsSurfaceTexture.h" 1.46 +#include "GeckoProfiler.h" 1.47 +#include "nsMemoryPressure.h" 1.48 + 1.49 +using namespace mozilla; 1.50 +using namespace mozilla::dom; 1.51 +using namespace mozilla::dom::mobilemessage; 1.52 +using namespace mozilla::layers; 1.53 +using namespace mozilla::widget::android; 1.54 + 1.55 +/* Forward declare all the JNI methods as extern "C" */ 1.56 + 1.57 +extern "C" { 1.58 +/* 1.59 + * Incoming JNI methods 1.60 + */ 1.61 + 1.62 +NS_EXPORT void JNICALL 1.63 +Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv *jenv, jclass jc) 1.64 +{ 1.65 + AndroidBridge::ConstructBridge(jenv); 1.66 +} 1.67 + 1.68 +NS_EXPORT void JNICALL 1.69 +Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoOfEvent(JNIEnv *jenv, jclass jc, jobject event) 1.70 +{ 1.71 + // poke the appshell 1.72 + if (nsAppShell::gAppShell) 1.73 + nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeFromJavaObject(jenv, event)); 1.74 +} 1.75 + 1.76 +NS_EXPORT void JNICALL 1.77 +Java_org_mozilla_gecko_GeckoAppShell_processNextNativeEvent(JNIEnv *jenv, jclass, jboolean mayWait) 1.78 +{ 1.79 + // poke the appshell 1.80 + if (nsAppShell::gAppShell) 1.81 + nsAppShell::gAppShell->ProcessNextNativeEvent(mayWait != JNI_FALSE); 1.82 +} 1.83 + 1.84 +NS_EXPORT void JNICALL 1.85 +Java_org_mozilla_gecko_GeckoAppShell_setLayerClient(JNIEnv *jenv, jclass, jobject obj) 1.86 +{ 1.87 + AndroidBridge::Bridge()->SetLayerClient(jenv, obj); 1.88 +} 1.89 + 1.90 +NS_EXPORT void JNICALL 1.91 +Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv *jenv, jclass jc) 1.92 +{ 1.93 + if (nsAppShell::gAppShell) 1.94 + nsAppShell::gAppShell->OnResume(); 1.95 +} 1.96 + 1.97 +NS_EXPORT void JNICALL 1.98 +Java_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv *jenv, jclass, jstring jStackTrace) 1.99 +{ 1.100 +#ifdef MOZ_CRASHREPORTER 1.101 + const nsJNIString stackTrace16(jStackTrace, jenv); 1.102 + const NS_ConvertUTF16toUTF8 stackTrace8(stackTrace16); 1.103 + CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("JavaStackTrace"), stackTrace8); 1.104 +#endif // MOZ_CRASHREPORTER 1.105 + 1.106 + abort(); 1.107 +} 1.108 + 1.109 +NS_EXPORT void JNICALL 1.110 +Java_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv* jenv, jclass, 1.111 + jdouble aLevel, 1.112 + jboolean aCharging, 1.113 + jdouble aRemainingTime) 1.114 +{ 1.115 + class NotifyBatteryChangeRunnable : public nsRunnable { 1.116 + public: 1.117 + NotifyBatteryChangeRunnable(double aLevel, bool aCharging, double aRemainingTime) 1.118 + : mLevel(aLevel) 1.119 + , mCharging(aCharging) 1.120 + , mRemainingTime(aRemainingTime) 1.121 + {} 1.122 + 1.123 + NS_IMETHODIMP Run() { 1.124 + hal::NotifyBatteryChange(hal::BatteryInformation(mLevel, mCharging, mRemainingTime)); 1.125 + return NS_OK; 1.126 + } 1.127 + 1.128 + private: 1.129 + double mLevel; 1.130 + bool mCharging; 1.131 + double mRemainingTime; 1.132 + }; 1.133 + 1.134 + nsCOMPtr<nsIRunnable> runnable = new NotifyBatteryChangeRunnable(aLevel, aCharging, aRemainingTime); 1.135 + NS_DispatchToMainThread(runnable); 1.136 +} 1.137 + 1.138 +#ifdef MOZ_WEBSMS_BACKEND 1.139 + 1.140 +NS_EXPORT void JNICALL 1.141 +Java_org_mozilla_gecko_GeckoSmsManager_notifySmsReceived(JNIEnv* jenv, jclass, 1.142 + jstring aSender, 1.143 + jstring aBody, 1.144 + jint aMessageClass, 1.145 + jlong aTimestamp) 1.146 +{ 1.147 + class NotifySmsReceivedRunnable : public nsRunnable { 1.148 + public: 1.149 + NotifySmsReceivedRunnable(const SmsMessageData& aMessageData) 1.150 + : mMessageData(aMessageData) 1.151 + {} 1.152 + 1.153 + NS_IMETHODIMP Run() { 1.154 + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); 1.155 + if (!obs) { 1.156 + return NS_OK; 1.157 + } 1.158 + 1.159 + nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData); 1.160 + obs->NotifyObservers(message, kSmsReceivedObserverTopic, nullptr); 1.161 + return NS_OK; 1.162 + } 1.163 + 1.164 + private: 1.165 + SmsMessageData mMessageData; 1.166 + }; 1.167 + 1.168 + // TODO Need to correct the message `threadId` parameter value. Bug 859098 1.169 + SmsMessageData message(0, 0, eDeliveryState_Received, eDeliveryStatus_Success, 1.170 + nsJNIString(aSender, jenv), EmptyString(), 1.171 + nsJNIString(aBody, jenv), 1.172 + static_cast<MessageClass>(aMessageClass), 1.173 + aTimestamp, false); 1.174 + 1.175 + nsCOMPtr<nsIRunnable> runnable = new NotifySmsReceivedRunnable(message); 1.176 + NS_DispatchToMainThread(runnable); 1.177 +} 1.178 + 1.179 +NS_EXPORT void JNICALL 1.180 +Java_org_mozilla_gecko_GeckoSmsManager_notifySmsSent(JNIEnv* jenv, jclass, 1.181 + jint aId, 1.182 + jstring aReceiver, 1.183 + jstring aBody, 1.184 + jlong aTimestamp, 1.185 + jint aRequestId) 1.186 +{ 1.187 + class NotifySmsSentRunnable : public nsRunnable { 1.188 + public: 1.189 + NotifySmsSentRunnable(const SmsMessageData& aMessageData, 1.190 + int32_t aRequestId) 1.191 + : mMessageData(aMessageData) 1.192 + , mRequestId(aRequestId) 1.193 + {} 1.194 + 1.195 + NS_IMETHODIMP Run() { 1.196 + /* 1.197 + * First, we are going to notify all SmsManager that a message has 1.198 + * been sent. Then, we will notify the SmsRequest object about it. 1.199 + */ 1.200 + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); 1.201 + if (!obs) { 1.202 + return NS_OK; 1.203 + } 1.204 + 1.205 + nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData); 1.206 + obs->NotifyObservers(message, kSmsSentObserverTopic, nullptr); 1.207 + 1.208 + nsCOMPtr<nsIMobileMessageCallback> request = 1.209 + AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); 1.210 + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); 1.211 + 1.212 + request->NotifyMessageSent(message); 1.213 + return NS_OK; 1.214 + } 1.215 + 1.216 + private: 1.217 + SmsMessageData mMessageData; 1.218 + int32_t mRequestId; 1.219 + }; 1.220 + 1.221 + // TODO Need to add the message `messageClass` parameter value. Bug 804476 1.222 + // TODO Need to correct the message `threadId` parameter value. Bug 859098 1.223 + SmsMessageData message(aId, 0, eDeliveryState_Sent, eDeliveryStatus_Pending, 1.224 + EmptyString(), nsJNIString(aReceiver, jenv), 1.225 + nsJNIString(aBody, jenv), eMessageClass_Normal, 1.226 + aTimestamp, true); 1.227 + 1.228 + nsCOMPtr<nsIRunnable> runnable = new NotifySmsSentRunnable(message, aRequestId); 1.229 + NS_DispatchToMainThread(runnable); 1.230 +} 1.231 + 1.232 +NS_EXPORT void JNICALL 1.233 +Java_org_mozilla_gecko_GeckoSmsManager_notifySmsDelivery(JNIEnv* jenv, jclass, 1.234 + jint aId, 1.235 + jint aDeliveryStatus, 1.236 + jstring aReceiver, 1.237 + jstring aBody, 1.238 + jlong aTimestamp) 1.239 +{ 1.240 + class NotifySmsDeliveredRunnable : public nsRunnable { 1.241 + public: 1.242 + NotifySmsDeliveredRunnable(const SmsMessageData& aMessageData) 1.243 + : mMessageData(aMessageData) 1.244 + {} 1.245 + 1.246 + NS_IMETHODIMP Run() { 1.247 + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); 1.248 + if (!obs) { 1.249 + return NS_OK; 1.250 + } 1.251 + 1.252 + nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData); 1.253 + const char* topic = (mMessageData.deliveryStatus() == eDeliveryStatus_Success) 1.254 + ? kSmsDeliverySuccessObserverTopic 1.255 + : kSmsDeliveryErrorObserverTopic; 1.256 + obs->NotifyObservers(message, topic, nullptr); 1.257 + 1.258 + return NS_OK; 1.259 + } 1.260 + 1.261 + private: 1.262 + SmsMessageData mMessageData; 1.263 + }; 1.264 + 1.265 + // TODO Need to add the message `messageClass` parameter value. Bug 804476 1.266 + // TODO Need to correct the message `threadId` parameter value. Bug 859098 1.267 + SmsMessageData message(aId, 0, eDeliveryState_Sent, 1.268 + static_cast<DeliveryStatus>(aDeliveryStatus), 1.269 + EmptyString(), nsJNIString(aReceiver, jenv), 1.270 + nsJNIString(aBody, jenv), eMessageClass_Normal, 1.271 + aTimestamp, true); 1.272 + 1.273 + nsCOMPtr<nsIRunnable> runnable = new NotifySmsDeliveredRunnable(message); 1.274 + NS_DispatchToMainThread(runnable); 1.275 +} 1.276 + 1.277 +NS_EXPORT void JNICALL 1.278 +Java_org_mozilla_gecko_GeckoSmsManager_notifySmsSendFailed(JNIEnv* jenv, jclass, 1.279 + jint aError, 1.280 + jint aRequestId) 1.281 +{ 1.282 + class NotifySmsSendFailedRunnable : public nsRunnable { 1.283 + public: 1.284 + NotifySmsSendFailedRunnable(int32_t aError, 1.285 + int32_t aRequestId) 1.286 + : mError(aError) 1.287 + , mRequestId(aRequestId) 1.288 + {} 1.289 + 1.290 + NS_IMETHODIMP Run() { 1.291 + nsCOMPtr<nsIMobileMessageCallback> request = 1.292 + AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); 1.293 + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); 1.294 + 1.295 + request->NotifySendMessageFailed(mError); 1.296 + return NS_OK; 1.297 + } 1.298 + 1.299 + private: 1.300 + int32_t mError; 1.301 + int32_t mRequestId; 1.302 + }; 1.303 + 1.304 + 1.305 + nsCOMPtr<nsIRunnable> runnable = 1.306 + new NotifySmsSendFailedRunnable(aError, aRequestId); 1.307 + NS_DispatchToMainThread(runnable); 1.308 +} 1.309 + 1.310 +NS_EXPORT void JNICALL 1.311 +Java_org_mozilla_gecko_GeckoSmsManager_notifyGetSms(JNIEnv* jenv, jclass, 1.312 + jint aId, 1.313 + jint aDeliveryStatus, 1.314 + jstring aReceiver, 1.315 + jstring aSender, 1.316 + jstring aBody, 1.317 + jlong aTimestamp, 1.318 + jint aRequestId) 1.319 +{ 1.320 + class NotifyGetSmsRunnable : public nsRunnable { 1.321 + public: 1.322 + NotifyGetSmsRunnable(const SmsMessageData& aMessageData, 1.323 + int32_t aRequestId) 1.324 + : mMessageData(aMessageData) 1.325 + , mRequestId(aRequestId) 1.326 + {} 1.327 + 1.328 + NS_IMETHODIMP Run() { 1.329 + nsCOMPtr<nsIMobileMessageCallback> request = 1.330 + AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); 1.331 + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); 1.332 + 1.333 + nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData); 1.334 + request->NotifyMessageGot(message); 1.335 + return NS_OK; 1.336 + } 1.337 + 1.338 + private: 1.339 + SmsMessageData mMessageData; 1.340 + int32_t mRequestId; 1.341 + }; 1.342 + 1.343 + nsJNIString receiver = nsJNIString(aReceiver, jenv); 1.344 + DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received 1.345 + : eDeliveryState_Sent; 1.346 + 1.347 + // TODO Need to add the message `read` parameter value. Bug 748391 1.348 + // TODO Need to add the message `messageClass` parameter value. Bug 804476 1.349 + // TODO Need to correct the message `threadId` parameter value. Bug 859098 1.350 + SmsMessageData message(aId, 0, state, 1.351 + static_cast<DeliveryStatus>(aDeliveryStatus), 1.352 + nsJNIString(aSender, jenv), receiver, 1.353 + nsJNIString(aBody, jenv), eMessageClass_Normal, 1.354 + aTimestamp, true); 1.355 + 1.356 + nsCOMPtr<nsIRunnable> runnable = new NotifyGetSmsRunnable(message, aRequestId); 1.357 + NS_DispatchToMainThread(runnable); 1.358 +} 1.359 + 1.360 +NS_EXPORT void JNICALL 1.361 +Java_org_mozilla_gecko_GeckoSmsManager_notifyGetSmsFailed(JNIEnv* jenv, jclass, 1.362 + jint aError, 1.363 + jint aRequestId) 1.364 +{ 1.365 + class NotifyGetSmsFailedRunnable : public nsRunnable { 1.366 + public: 1.367 + NotifyGetSmsFailedRunnable(int32_t aError, 1.368 + int32_t aRequestId) 1.369 + : mError(aError) 1.370 + , mRequestId(aRequestId) 1.371 + {} 1.372 + 1.373 + NS_IMETHODIMP Run() { 1.374 + nsCOMPtr<nsIMobileMessageCallback> request = 1.375 + AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); 1.376 + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); 1.377 + 1.378 + request->NotifyGetMessageFailed(mError); 1.379 + return NS_OK; 1.380 + } 1.381 + 1.382 + private: 1.383 + int32_t mError; 1.384 + int32_t mRequestId; 1.385 + }; 1.386 + 1.387 + 1.388 + nsCOMPtr<nsIRunnable> runnable = 1.389 + new NotifyGetSmsFailedRunnable(aError, aRequestId); 1.390 + NS_DispatchToMainThread(runnable); 1.391 +} 1.392 + 1.393 +NS_EXPORT void JNICALL 1.394 +Java_org_mozilla_gecko_GeckoSmsManager_notifySmsDeleted(JNIEnv* jenv, jclass, 1.395 + jboolean aDeleted, 1.396 + jint aRequestId) 1.397 +{ 1.398 + class NotifySmsDeletedRunnable : public nsRunnable { 1.399 + public: 1.400 + NotifySmsDeletedRunnable(bool aDeleted, int32_t aRequestId) 1.401 + : mDeleted(aDeleted) 1.402 + , mRequestId(aRequestId) 1.403 + {} 1.404 + 1.405 + NS_IMETHODIMP Run() { 1.406 + nsCOMPtr<nsIMobileMessageCallback> request = 1.407 + AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); 1.408 + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); 1.409 + 1.410 + // For android, we support only single SMS deletion. 1.411 + request->NotifyMessageDeleted(&mDeleted, 1); 1.412 + return NS_OK; 1.413 + } 1.414 + 1.415 + private: 1.416 + bool mDeleted; 1.417 + int32_t mRequestId; 1.418 + }; 1.419 + 1.420 + 1.421 + nsCOMPtr<nsIRunnable> runnable = 1.422 + new NotifySmsDeletedRunnable(aDeleted, aRequestId); 1.423 + NS_DispatchToMainThread(runnable); 1.424 +} 1.425 + 1.426 +NS_EXPORT void JNICALL 1.427 +Java_org_mozilla_gecko_GeckoSmsManager_notifySmsDeleteFailed(JNIEnv* jenv, jclass, 1.428 + jint aError, 1.429 + jint aRequestId) 1.430 +{ 1.431 + class NotifySmsDeleteFailedRunnable : public nsRunnable { 1.432 + public: 1.433 + NotifySmsDeleteFailedRunnable(int32_t aError, 1.434 + int32_t aRequestId) 1.435 + : mError(aError) 1.436 + , mRequestId(aRequestId) 1.437 + {} 1.438 + 1.439 + NS_IMETHODIMP Run() { 1.440 + nsCOMPtr<nsIMobileMessageCallback> request = 1.441 + AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); 1.442 + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); 1.443 + 1.444 + request->NotifyDeleteMessageFailed(mError); 1.445 + return NS_OK; 1.446 + } 1.447 + 1.448 + private: 1.449 + int32_t mError; 1.450 + int32_t mRequestId; 1.451 + }; 1.452 + 1.453 + 1.454 + nsCOMPtr<nsIRunnable> runnable = 1.455 + new NotifySmsDeleteFailedRunnable(aError, aRequestId); 1.456 + NS_DispatchToMainThread(runnable); 1.457 +} 1.458 + 1.459 +NS_EXPORT void JNICALL 1.460 +Java_org_mozilla_gecko_GeckoSmsManager_notifyNoMessageInList(JNIEnv* jenv, jclass, 1.461 + jint aRequestId) 1.462 +{ 1.463 + class NotifyNoMessageInListRunnable : public nsRunnable { 1.464 + public: 1.465 + NotifyNoMessageInListRunnable(int32_t aRequestId) 1.466 + : mRequestId(aRequestId) 1.467 + {} 1.468 + 1.469 + NS_IMETHODIMP Run() { 1.470 + nsCOMPtr<nsIMobileMessageCallback> request = 1.471 + AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); 1.472 + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); 1.473 + 1.474 + request->NotifyNoMessageInList(); 1.475 + return NS_OK; 1.476 + } 1.477 + 1.478 + private: 1.479 + int32_t mRequestId; 1.480 + }; 1.481 + 1.482 + 1.483 + nsCOMPtr<nsIRunnable> runnable = 1.484 + new NotifyNoMessageInListRunnable(aRequestId); 1.485 + NS_DispatchToMainThread(runnable); 1.486 +} 1.487 + 1.488 +NS_EXPORT void JNICALL 1.489 +Java_org_mozilla_gecko_GeckoSmsManager_notifyListCreated(JNIEnv* jenv, jclass, 1.490 + jint aListId, 1.491 + jint aMessageId, 1.492 + jint aDeliveryStatus, 1.493 + jstring aReceiver, 1.494 + jstring aSender, 1.495 + jstring aBody, 1.496 + jlong aTimestamp, 1.497 + jint aRequestId) 1.498 +{ 1.499 + class NotifyCreateMessageListRunnable : public nsRunnable { 1.500 + public: 1.501 + NotifyCreateMessageListRunnable(int32_t aListId, 1.502 + const SmsMessageData& aMessageData, 1.503 + int32_t aRequestId) 1.504 + : mListId(aListId) 1.505 + , mMessageData(aMessageData) 1.506 + , mRequestId(aRequestId) 1.507 + {} 1.508 + 1.509 + NS_IMETHODIMP Run() { 1.510 + nsCOMPtr<nsIMobileMessageCallback> request = 1.511 + AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); 1.512 + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); 1.513 + 1.514 + nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData); 1.515 + request->NotifyMessageListCreated(mListId, message); 1.516 + return NS_OK; 1.517 + } 1.518 + 1.519 + private: 1.520 + int32_t mListId; 1.521 + SmsMessageData mMessageData; 1.522 + int32_t mRequestId; 1.523 + }; 1.524 + 1.525 + 1.526 + nsJNIString receiver = nsJNIString(aReceiver, jenv); 1.527 + DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received 1.528 + : eDeliveryState_Sent; 1.529 + 1.530 + // TODO Need to add the message `read` parameter value. Bug 748391 1.531 + // TODO Need to add the message `messageClass` parameter value. Bug 804476 1.532 + // TODO Need to correct the message `threadId` parameter value. Bug 859098 1.533 + SmsMessageData message(aMessageId, 0, state, 1.534 + static_cast<DeliveryStatus>(aDeliveryStatus), 1.535 + nsJNIString(aSender, jenv), receiver, 1.536 + nsJNIString(aBody, jenv), eMessageClass_Normal, 1.537 + aTimestamp, true); 1.538 + 1.539 + nsCOMPtr<nsIRunnable> runnable = 1.540 + new NotifyCreateMessageListRunnable(aListId, message, aRequestId); 1.541 + NS_DispatchToMainThread(runnable); 1.542 +} 1.543 + 1.544 +NS_EXPORT void JNICALL 1.545 +Java_org_mozilla_gecko_GeckoSmsManager_notifyGotNextMessage(JNIEnv* jenv, jclass, 1.546 + jint aMessageId, 1.547 + jint aDeliveryStatus, 1.548 + jstring aReceiver, 1.549 + jstring aSender, 1.550 + jstring aBody, 1.551 + jlong aTimestamp, 1.552 + jint aRequestId) 1.553 +{ 1.554 + class NotifyGotNextMessageRunnable : public nsRunnable { 1.555 + public: 1.556 + NotifyGotNextMessageRunnable(const SmsMessageData& aMessageData, 1.557 + int32_t aRequestId) 1.558 + : mMessageData(aMessageData) 1.559 + , mRequestId(aRequestId) 1.560 + {} 1.561 + 1.562 + NS_IMETHODIMP Run() { 1.563 + nsCOMPtr<nsIMobileMessageCallback> request = 1.564 + AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); 1.565 + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); 1.566 + 1.567 + nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData); 1.568 + request->NotifyNextMessageInListGot(message); 1.569 + return NS_OK; 1.570 + } 1.571 + 1.572 + private: 1.573 + SmsMessageData mMessageData; 1.574 + int32_t mRequestId; 1.575 + }; 1.576 + 1.577 + 1.578 + nsJNIString receiver = nsJNIString(aReceiver, jenv); 1.579 + DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received 1.580 + : eDeliveryState_Sent; 1.581 + 1.582 + // TODO Need to add the message `read` parameter value. Bug 748391 1.583 + // TODO Need to add the message `messageClass` parameter value. Bug 804476 1.584 + // TODO Need to correct the message `threadId` parameter value. Bug 859098 1.585 + SmsMessageData message(aMessageId, 0, state, 1.586 + static_cast<DeliveryStatus>(aDeliveryStatus), 1.587 + nsJNIString(aSender, jenv), receiver, 1.588 + nsJNIString(aBody, jenv), eMessageClass_Normal, 1.589 + aTimestamp, true); 1.590 + 1.591 + nsCOMPtr<nsIRunnable> runnable = 1.592 + new NotifyGotNextMessageRunnable(message, aRequestId); 1.593 + NS_DispatchToMainThread(runnable); 1.594 +} 1.595 + 1.596 +NS_EXPORT void JNICALL 1.597 +Java_org_mozilla_gecko_GeckoSmsManager_notifyReadingMessageListFailed(JNIEnv* jenv, jclass, 1.598 + jint aError, 1.599 + jint aRequestId) 1.600 +{ 1.601 + class NotifyReadListFailedRunnable : public nsRunnable { 1.602 + public: 1.603 + NotifyReadListFailedRunnable(int32_t aError, 1.604 + int32_t aRequestId) 1.605 + : mError(aError) 1.606 + , mRequestId(aRequestId) 1.607 + {} 1.608 + 1.609 + NS_IMETHODIMP Run() { 1.610 + nsCOMPtr<nsIMobileMessageCallback> request = 1.611 + AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); 1.612 + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); 1.613 + 1.614 + request->NotifyReadMessageListFailed(mError); 1.615 + return NS_OK; 1.616 + } 1.617 + 1.618 + private: 1.619 + int32_t mError; 1.620 + int32_t mRequestId; 1.621 + }; 1.622 + 1.623 + 1.624 + nsCOMPtr<nsIRunnable> runnable = 1.625 + new NotifyReadListFailedRunnable(aError, aRequestId); 1.626 + NS_DispatchToMainThread(runnable); 1.627 +} 1.628 + 1.629 +#endif // MOZ_WEBSMS_BACKEND 1.630 + 1.631 +NS_EXPORT void JNICALL 1.632 +Java_org_mozilla_gecko_GeckoAppShell_scheduleComposite(JNIEnv*, jclass) 1.633 +{ 1.634 + nsWindow::ScheduleComposite(); 1.635 +} 1.636 + 1.637 +NS_EXPORT void JNICALL 1.638 +Java_org_mozilla_gecko_GeckoAppShell_scheduleResumeComposition(JNIEnv*, jclass, jint width, jint height) 1.639 +{ 1.640 + nsWindow::ScheduleResumeComposition(width, height); 1.641 +} 1.642 + 1.643 +NS_EXPORT float JNICALL 1.644 +Java_org_mozilla_gecko_GeckoAppShell_computeRenderIntegrity(JNIEnv*, jclass) 1.645 +{ 1.646 + return nsWindow::ComputeRenderIntegrity(); 1.647 +} 1.648 + 1.649 +NS_EXPORT void JNICALL 1.650 +Java_org_mozilla_gecko_GeckoAppShell_notifyFilePickerResult(JNIEnv* jenv, jclass, jstring filePath, jlong callback) 1.651 +{ 1.652 + class NotifyFilePickerResultRunnable : public nsRunnable { 1.653 + public: 1.654 + NotifyFilePickerResultRunnable(nsString& fileDir, long callback) : 1.655 + mFileDir(fileDir), mCallback(callback) {} 1.656 + 1.657 + NS_IMETHODIMP Run() { 1.658 + nsFilePickerCallback* handler = (nsFilePickerCallback*)mCallback; 1.659 + handler->handleResult(mFileDir); 1.660 + handler->Release(); 1.661 + return NS_OK; 1.662 + } 1.663 + private: 1.664 + nsString mFileDir; 1.665 + long mCallback; 1.666 + }; 1.667 + nsString path = nsJNIString(filePath, jenv); 1.668 + 1.669 + nsCOMPtr<nsIRunnable> runnable = 1.670 + new NotifyFilePickerResultRunnable(path, (long)callback); 1.671 + NS_DispatchToMainThread(runnable); 1.672 +} 1.673 + 1.674 +static int 1.675 +NextPowerOfTwo(int value) { 1.676 + // code taken from http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.html 1.677 + if (0 == value--) { 1.678 + return 1; 1.679 + } 1.680 + value = (value >> 1) | value; 1.681 + value = (value >> 2) | value; 1.682 + value = (value >> 4) | value; 1.683 + value = (value >> 8) | value; 1.684 + value = (value >> 16) | value; 1.685 + return value + 1; 1.686 +} 1.687 + 1.688 +#define MAX_LOCK_ATTEMPTS 10 1.689 + 1.690 +static bool LockWindowWithRetry(void* window, unsigned char** bits, int* width, int* height, int* format, int* stride) 1.691 +{ 1.692 + int count = 0; 1.693 + 1.694 + while (count < MAX_LOCK_ATTEMPTS) { 1.695 + if (AndroidBridge::Bridge()->LockWindow(window, bits, width, height, format, stride)) 1.696 + return true; 1.697 + 1.698 + count++; 1.699 + usleep(500); 1.700 + } 1.701 + 1.702 + return false; 1.703 +} 1.704 + 1.705 +NS_EXPORT jobject JNICALL 1.706 +Java_org_mozilla_gecko_GeckoAppShell_getSurfaceBits(JNIEnv* jenv, jclass, jobject surface) 1.707 +{ 1.708 + static jclass jSurfaceBitsClass = nullptr; 1.709 + static jmethodID jSurfaceBitsCtor = 0; 1.710 + static jfieldID jSurfaceBitsWidth, jSurfaceBitsHeight, jSurfaceBitsFormat, jSurfaceBitsBuffer; 1.711 + 1.712 + jobject surfaceBits = nullptr; 1.713 + unsigned char* bitsCopy = nullptr; 1.714 + int dstWidth, dstHeight, dstSize; 1.715 + 1.716 + void* window = AndroidBridge::Bridge()->AcquireNativeWindow(jenv, surface); 1.717 + if (!window) 1.718 + return nullptr; 1.719 + 1.720 + unsigned char* bits; 1.721 + int srcWidth, srcHeight, format, srcStride; 1.722 + 1.723 + // So we lock/unlock once here in order to get whatever is currently the front buffer. It sucks. 1.724 + if (!LockWindowWithRetry(window, &bits, &srcWidth, &srcHeight, &format, &srcStride)) 1.725 + return nullptr; 1.726 + 1.727 + AndroidBridge::Bridge()->UnlockWindow(window); 1.728 + 1.729 + // This is lock will result in the front buffer, since the last unlock rotated it to the back. Probably. 1.730 + if (!LockWindowWithRetry(window, &bits, &srcWidth, &srcHeight, &format, &srcStride)) 1.731 + return nullptr; 1.732 + 1.733 + // These are from android.graphics.PixelFormat 1.734 + int bpp; 1.735 + switch (format) { 1.736 + case 1: // RGBA_8888 1.737 + bpp = 4; 1.738 + break; 1.739 + case 4: // RGB_565 1.740 + bpp = 2; 1.741 + break; 1.742 + default: 1.743 + goto cleanup; 1.744 + } 1.745 + 1.746 + dstWidth = NextPowerOfTwo(srcWidth); 1.747 + dstHeight = NextPowerOfTwo(srcHeight); 1.748 + dstSize = dstWidth * dstHeight * bpp; 1.749 + 1.750 + bitsCopy = (unsigned char*)malloc(dstSize); 1.751 + bzero(bitsCopy, dstSize); 1.752 + for (int i = 0; i < srcHeight; i++) { 1.753 + memcpy(bitsCopy + ((dstHeight - i - 1) * dstWidth * bpp), bits + (i * srcStride * bpp), srcStride * bpp); 1.754 + } 1.755 + 1.756 + if (!jSurfaceBitsClass) { 1.757 + jSurfaceBitsClass = (jclass)jenv->NewGlobalRef(jenv->FindClass("org/mozilla/gecko/SurfaceBits")); 1.758 + jSurfaceBitsCtor = jenv->GetMethodID(jSurfaceBitsClass, "<init>", "()V"); 1.759 + 1.760 + jSurfaceBitsWidth = jenv->GetFieldID(jSurfaceBitsClass, "width", "I"); 1.761 + jSurfaceBitsHeight = jenv->GetFieldID(jSurfaceBitsClass, "height", "I"); 1.762 + jSurfaceBitsFormat = jenv->GetFieldID(jSurfaceBitsClass, "format", "I"); 1.763 + jSurfaceBitsBuffer = jenv->GetFieldID(jSurfaceBitsClass, "buffer", "Ljava/nio/ByteBuffer;"); 1.764 + } 1.765 + 1.766 + surfaceBits = jenv->NewObject(jSurfaceBitsClass, jSurfaceBitsCtor); 1.767 + jenv->SetIntField(surfaceBits, jSurfaceBitsWidth, dstWidth); 1.768 + jenv->SetIntField(surfaceBits, jSurfaceBitsHeight, dstHeight); 1.769 + jenv->SetIntField(surfaceBits, jSurfaceBitsFormat, format); 1.770 + jenv->SetObjectField(surfaceBits, jSurfaceBitsBuffer, jenv->NewDirectByteBuffer(bitsCopy, dstSize)); 1.771 + 1.772 +cleanup: 1.773 + AndroidBridge::Bridge()->UnlockWindow(window); 1.774 + AndroidBridge::Bridge()->ReleaseNativeWindow(window); 1.775 + 1.776 + return surfaceBits; 1.777 +} 1.778 + 1.779 +NS_EXPORT void JNICALL 1.780 +Java_org_mozilla_gecko_GeckoAppShell_onFullScreenPluginHidden(JNIEnv* jenv, jclass, jobject view) 1.781 +{ 1.782 + class ExitFullScreenRunnable : public nsRunnable { 1.783 + public: 1.784 + ExitFullScreenRunnable(jobject view) : mView(view) {} 1.785 + 1.786 + NS_IMETHODIMP Run() { 1.787 + JNIEnv* env = AndroidBridge::GetJNIEnv(); 1.788 + nsPluginInstanceOwner::ExitFullScreen(mView); 1.789 + env->DeleteGlobalRef(mView); 1.790 + return NS_OK; 1.791 + } 1.792 + 1.793 + private: 1.794 + jobject mView; 1.795 + }; 1.796 + 1.797 + nsCOMPtr<nsIRunnable> runnable = new ExitFullScreenRunnable(jenv->NewGlobalRef(view)); 1.798 + NS_DispatchToMainThread(runnable); 1.799 +} 1.800 + 1.801 +NS_EXPORT jobject JNICALL 1.802 +Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue(JNIEnv* jenv, jclass, jobject queue) 1.803 +{ 1.804 + static jclass jMessageQueueCls = nullptr; 1.805 + static jfieldID jMessagesField; 1.806 + static jmethodID jNextMethod; 1.807 + if (!jMessageQueueCls) { 1.808 + jMessageQueueCls = (jclass) jenv->NewGlobalRef(jenv->FindClass("android/os/MessageQueue")); 1.809 + jNextMethod = jenv->GetMethodID(jMessageQueueCls, "next", "()Landroid/os/Message;"); 1.810 + jMessagesField = jenv->GetFieldID(jMessageQueueCls, "mMessages", "Landroid/os/Message;"); 1.811 + } 1.812 + 1.813 + if (!jMessageQueueCls || !jNextMethod) 1.814 + return nullptr; 1.815 + 1.816 + if (jMessagesField) { 1.817 + jobject msg = jenv->GetObjectField(queue, jMessagesField); 1.818 + // if queue.mMessages is null, queue.next() will block, which we don't want 1.819 + // It turns out to be an order of magnitude more performant to do this extra check here and 1.820 + // block less vs. one fewer checks here and more blocking. 1.821 + if (!msg) { 1.822 + return nullptr; 1.823 + } 1.824 + } 1.825 + return jenv->CallObjectMethod(queue, jNextMethod); 1.826 +} 1.827 + 1.828 +NS_EXPORT void JNICALL 1.829 +Java_org_mozilla_gecko_GeckoAppShell_onSurfaceTextureFrameAvailable(JNIEnv* jenv, jclass, jobject surfaceTexture, jint id) 1.830 +{ 1.831 + nsSurfaceTexture* st = nsSurfaceTexture::Find(id); 1.832 + if (!st) { 1.833 + __android_log_print(ANDROID_LOG_ERROR, "GeckoJNI", "Failed to find nsSurfaceTexture with id %d", id); 1.834 + return; 1.835 + } 1.836 + 1.837 + st->NotifyFrameAvailable(); 1.838 +} 1.839 + 1.840 +NS_EXPORT void JNICALL 1.841 +Java_org_mozilla_gecko_GeckoAppShell_dispatchMemoryPressure(JNIEnv* jenv, jclass) 1.842 +{ 1.843 + NS_DispatchMemoryPressure(MemPressure_New); 1.844 +} 1.845 + 1.846 +NS_EXPORT jdouble JNICALL 1.847 +Java_org_mozilla_gecko_GeckoJavaSampler_getProfilerTime(JNIEnv *jenv, jclass jc) 1.848 +{ 1.849 + return profiler_time(); 1.850 +} 1.851 + 1.852 +NS_EXPORT void JNICALL 1.853 +Java_org_mozilla_gecko_gfx_NativePanZoomController_abortAnimation(JNIEnv* env, jobject instance) 1.854 +{ 1.855 + APZCTreeManager *controller = nsWindow::GetAPZCTreeManager(); 1.856 + if (controller) { 1.857 + // TODO: Pass in correct values for presShellId and viewId. 1.858 + controller->CancelAnimation(ScrollableLayerGuid(nsWindow::RootLayerTreeId(), 0, 0)); 1.859 + } 1.860 +} 1.861 + 1.862 +NS_EXPORT void JNICALL 1.863 +Java_org_mozilla_gecko_gfx_NativePanZoomController_init(JNIEnv* env, jobject instance) 1.864 +{ 1.865 + if (!AndroidBridge::Bridge()) { 1.866 + return; 1.867 + } 1.868 + 1.869 + NativePanZoomController* oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(instance); 1.870 + if (oldRef && !oldRef->isNull()) { 1.871 + MOZ_ASSERT(false, "Registering a new NPZC when we already have one"); 1.872 + delete oldRef; 1.873 + } 1.874 +} 1.875 + 1.876 +NS_EXPORT void JNICALL 1.877 +Java_org_mozilla_gecko_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, jobject instance, jobject event) 1.878 +{ 1.879 + APZCTreeManager *controller = nsWindow::GetAPZCTreeManager(); 1.880 + if (controller) { 1.881 + AndroidGeckoEvent* wrapper = AndroidGeckoEvent::MakeFromJavaObject(env, event); 1.882 + const MultiTouchInput& input = wrapper->MakeMultiTouchInput(nsWindow::TopWindow()); 1.883 + delete wrapper; 1.884 + if (input.mType >= 0) { 1.885 + controller->ReceiveInputEvent(input, nullptr); 1.886 + } 1.887 + } 1.888 +} 1.889 + 1.890 +NS_EXPORT void JNICALL 1.891 +Java_org_mozilla_gecko_gfx_NativePanZoomController_handleMotionEvent(JNIEnv* env, jobject instance, jobject event) 1.892 +{ 1.893 + // FIXME implement this 1.894 +} 1.895 + 1.896 +NS_EXPORT jlong JNICALL 1.897 +Java_org_mozilla_gecko_gfx_NativePanZoomController_runDelayedCallback(JNIEnv* env, jobject instance) 1.898 +{ 1.899 + if (!AndroidBridge::Bridge()) { 1.900 + return -1; 1.901 + } 1.902 + 1.903 + return AndroidBridge::Bridge()->RunDelayedTasks(); 1.904 +} 1.905 + 1.906 +NS_EXPORT void JNICALL 1.907 +Java_org_mozilla_gecko_gfx_NativePanZoomController_destroy(JNIEnv* env, jobject instance) 1.908 +{ 1.909 + if (!AndroidBridge::Bridge()) { 1.910 + return; 1.911 + } 1.912 + 1.913 + NativePanZoomController* oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(nullptr); 1.914 + if (!oldRef || oldRef->isNull()) { 1.915 + MOZ_ASSERT(false, "Clearing a non-existent NPZC"); 1.916 + } else { 1.917 + delete oldRef; 1.918 + } 1.919 +} 1.920 + 1.921 +NS_EXPORT void JNICALL 1.922 +Java_org_mozilla_gecko_gfx_NativePanZoomController_notifyDefaultActionPrevented(JNIEnv* env, jobject instance, jboolean prevented) 1.923 +{ 1.924 + APZCTreeManager *controller = nsWindow::GetAPZCTreeManager(); 1.925 + if (controller) { 1.926 + // TODO: Pass in correct values for presShellId and viewId. 1.927 + controller->ContentReceivedTouch(ScrollableLayerGuid(nsWindow::RootLayerTreeId(), 0, 0), prevented); 1.928 + } 1.929 +} 1.930 + 1.931 +NS_EXPORT jboolean JNICALL 1.932 +Java_org_mozilla_gecko_gfx_NativePanZoomController_getRedrawHint(JNIEnv* env, jobject instance) 1.933 +{ 1.934 + // FIXME implement this 1.935 + return true; 1.936 +} 1.937 + 1.938 +NS_EXPORT void JNICALL 1.939 +Java_org_mozilla_gecko_gfx_NativePanZoomController_setOverScrollMode(JNIEnv* env, jobject instance, jint overscrollMode) 1.940 +{ 1.941 + // FIXME implement this 1.942 +} 1.943 + 1.944 +NS_EXPORT jint JNICALL 1.945 +Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode(JNIEnv* env, jobject instance) 1.946 +{ 1.947 + // FIXME implement this 1.948 + return 0; 1.949 +} 1.950 + 1.951 +NS_EXPORT jboolean JNICALL 1.952 +Java_org_mozilla_gecko_ANRReporter_requestNativeStack(JNIEnv*, jclass, jboolean aUnwind) 1.953 +{ 1.954 + if (profiler_is_active()) { 1.955 + // Don't proceed if profiler is already running 1.956 + return JNI_FALSE; 1.957 + } 1.958 + // WARNING: we are on the ANR reporter thread at this point and it is 1.959 + // generally unsafe to use the profiler from off the main thread. However, 1.960 + // the risk here is limited because for most users, the profiler is not run 1.961 + // elsewhere. See the discussion in Bug 863777, comment 13 1.962 + const char *NATIVE_STACK_FEATURES[] = 1.963 + {"leaf", "threads", "privacy"}; 1.964 + const char *NATIVE_STACK_UNWIND_FEATURES[] = 1.965 + {"leaf", "threads", "privacy", "stackwalk"}; 1.966 + 1.967 + const char **features = NATIVE_STACK_FEATURES; 1.968 + size_t features_size = sizeof(NATIVE_STACK_FEATURES); 1.969 + if (aUnwind) { 1.970 + features = NATIVE_STACK_UNWIND_FEATURES; 1.971 + features_size = sizeof(NATIVE_STACK_UNWIND_FEATURES); 1.972 + // We want the new unwinder if the unwind mode has not been set yet 1.973 + putenv("MOZ_PROFILER_NEW=1"); 1.974 + } 1.975 + 1.976 + const char *NATIVE_STACK_THREADS[] = 1.977 + {"GeckoMain", "Compositor"}; 1.978 + // Buffer one sample and let the profiler wait a long time 1.979 + profiler_start(100, 10000, features, features_size / sizeof(char*), 1.980 + NATIVE_STACK_THREADS, sizeof(NATIVE_STACK_THREADS) / sizeof(char*)); 1.981 + return JNI_TRUE; 1.982 +} 1.983 + 1.984 +NS_EXPORT jstring JNICALL 1.985 +Java_org_mozilla_gecko_ANRReporter_getNativeStack(JNIEnv* jenv, jclass) 1.986 +{ 1.987 + if (!profiler_is_active()) { 1.988 + // Maybe profiler support is disabled? 1.989 + return nullptr; 1.990 + } 1.991 + char *profile = profiler_get_profile(); 1.992 + while (profile && !strlen(profile)) { 1.993 + // no sample yet? 1.994 + sched_yield(); 1.995 + profile = profiler_get_profile(); 1.996 + } 1.997 + jstring result = nullptr; 1.998 + if (profile) { 1.999 + result = jenv->NewStringUTF(profile); 1.1000 + free(profile); 1.1001 + } 1.1002 + return result; 1.1003 +} 1.1004 + 1.1005 +NS_EXPORT void JNICALL 1.1006 +Java_org_mozilla_gecko_ANRReporter_releaseNativeStack(JNIEnv* jenv, jclass) 1.1007 +{ 1.1008 + if (!profiler_is_active()) { 1.1009 + // Maybe profiler support is disabled? 1.1010 + return; 1.1011 + } 1.1012 + mozilla_sampler_stop(); 1.1013 +} 1.1014 + 1.1015 +}