widget/android/AndroidJNI.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "mozilla/Hal.h"
michael@0 7 #include "nsIFile.h"
michael@0 8 #include "nsString.h"
michael@0 9
michael@0 10 #include "AndroidBridge.h"
michael@0 11 #include "AndroidGraphicBuffer.h"
michael@0 12
michael@0 13 #include <jni.h>
michael@0 14 #include <pthread.h>
michael@0 15 #include <dlfcn.h>
michael@0 16 #include <stdio.h>
michael@0 17 #include <unistd.h>
michael@0 18 #include <sched.h>
michael@0 19
michael@0 20 #include "nsAppShell.h"
michael@0 21 #include "nsWindow.h"
michael@0 22 #include <android/log.h>
michael@0 23 #include "nsIObserverService.h"
michael@0 24 #include "mozilla/Services.h"
michael@0 25 #include "nsThreadUtils.h"
michael@0 26
michael@0 27 #ifdef MOZ_CRASHREPORTER
michael@0 28 #include "nsICrashReporter.h"
michael@0 29 #include "nsExceptionHandler.h"
michael@0 30 #endif
michael@0 31
michael@0 32 #include "mozilla/unused.h"
michael@0 33
michael@0 34 #include "mozilla/dom/SmsMessage.h"
michael@0 35 #include "mozilla/dom/mobilemessage/Constants.h"
michael@0 36 #include "mozilla/dom/mobilemessage/Types.h"
michael@0 37 #include "mozilla/dom/mobilemessage/PSms.h"
michael@0 38 #include "mozilla/dom/mobilemessage/SmsParent.h"
michael@0 39 #include "mozilla/layers/APZCTreeManager.h"
michael@0 40 #include "nsIMobileMessageDatabaseService.h"
michael@0 41 #include "nsPluginInstanceOwner.h"
michael@0 42 #include "nsSurfaceTexture.h"
michael@0 43 #include "GeckoProfiler.h"
michael@0 44 #include "nsMemoryPressure.h"
michael@0 45
michael@0 46 using namespace mozilla;
michael@0 47 using namespace mozilla::dom;
michael@0 48 using namespace mozilla::dom::mobilemessage;
michael@0 49 using namespace mozilla::layers;
michael@0 50 using namespace mozilla::widget::android;
michael@0 51
michael@0 52 /* Forward declare all the JNI methods as extern "C" */
michael@0 53
michael@0 54 extern "C" {
michael@0 55 /*
michael@0 56 * Incoming JNI methods
michael@0 57 */
michael@0 58
michael@0 59 NS_EXPORT void JNICALL
michael@0 60 Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv *jenv, jclass jc)
michael@0 61 {
michael@0 62 AndroidBridge::ConstructBridge(jenv);
michael@0 63 }
michael@0 64
michael@0 65 NS_EXPORT void JNICALL
michael@0 66 Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoOfEvent(JNIEnv *jenv, jclass jc, jobject event)
michael@0 67 {
michael@0 68 // poke the appshell
michael@0 69 if (nsAppShell::gAppShell)
michael@0 70 nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeFromJavaObject(jenv, event));
michael@0 71 }
michael@0 72
michael@0 73 NS_EXPORT void JNICALL
michael@0 74 Java_org_mozilla_gecko_GeckoAppShell_processNextNativeEvent(JNIEnv *jenv, jclass, jboolean mayWait)
michael@0 75 {
michael@0 76 // poke the appshell
michael@0 77 if (nsAppShell::gAppShell)
michael@0 78 nsAppShell::gAppShell->ProcessNextNativeEvent(mayWait != JNI_FALSE);
michael@0 79 }
michael@0 80
michael@0 81 NS_EXPORT void JNICALL
michael@0 82 Java_org_mozilla_gecko_GeckoAppShell_setLayerClient(JNIEnv *jenv, jclass, jobject obj)
michael@0 83 {
michael@0 84 AndroidBridge::Bridge()->SetLayerClient(jenv, obj);
michael@0 85 }
michael@0 86
michael@0 87 NS_EXPORT void JNICALL
michael@0 88 Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv *jenv, jclass jc)
michael@0 89 {
michael@0 90 if (nsAppShell::gAppShell)
michael@0 91 nsAppShell::gAppShell->OnResume();
michael@0 92 }
michael@0 93
michael@0 94 NS_EXPORT void JNICALL
michael@0 95 Java_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv *jenv, jclass, jstring jStackTrace)
michael@0 96 {
michael@0 97 #ifdef MOZ_CRASHREPORTER
michael@0 98 const nsJNIString stackTrace16(jStackTrace, jenv);
michael@0 99 const NS_ConvertUTF16toUTF8 stackTrace8(stackTrace16);
michael@0 100 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("JavaStackTrace"), stackTrace8);
michael@0 101 #endif // MOZ_CRASHREPORTER
michael@0 102
michael@0 103 abort();
michael@0 104 }
michael@0 105
michael@0 106 NS_EXPORT void JNICALL
michael@0 107 Java_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv* jenv, jclass,
michael@0 108 jdouble aLevel,
michael@0 109 jboolean aCharging,
michael@0 110 jdouble aRemainingTime)
michael@0 111 {
michael@0 112 class NotifyBatteryChangeRunnable : public nsRunnable {
michael@0 113 public:
michael@0 114 NotifyBatteryChangeRunnable(double aLevel, bool aCharging, double aRemainingTime)
michael@0 115 : mLevel(aLevel)
michael@0 116 , mCharging(aCharging)
michael@0 117 , mRemainingTime(aRemainingTime)
michael@0 118 {}
michael@0 119
michael@0 120 NS_IMETHODIMP Run() {
michael@0 121 hal::NotifyBatteryChange(hal::BatteryInformation(mLevel, mCharging, mRemainingTime));
michael@0 122 return NS_OK;
michael@0 123 }
michael@0 124
michael@0 125 private:
michael@0 126 double mLevel;
michael@0 127 bool mCharging;
michael@0 128 double mRemainingTime;
michael@0 129 };
michael@0 130
michael@0 131 nsCOMPtr<nsIRunnable> runnable = new NotifyBatteryChangeRunnable(aLevel, aCharging, aRemainingTime);
michael@0 132 NS_DispatchToMainThread(runnable);
michael@0 133 }
michael@0 134
michael@0 135 #ifdef MOZ_WEBSMS_BACKEND
michael@0 136
michael@0 137 NS_EXPORT void JNICALL
michael@0 138 Java_org_mozilla_gecko_GeckoSmsManager_notifySmsReceived(JNIEnv* jenv, jclass,
michael@0 139 jstring aSender,
michael@0 140 jstring aBody,
michael@0 141 jint aMessageClass,
michael@0 142 jlong aTimestamp)
michael@0 143 {
michael@0 144 class NotifySmsReceivedRunnable : public nsRunnable {
michael@0 145 public:
michael@0 146 NotifySmsReceivedRunnable(const SmsMessageData& aMessageData)
michael@0 147 : mMessageData(aMessageData)
michael@0 148 {}
michael@0 149
michael@0 150 NS_IMETHODIMP Run() {
michael@0 151 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
michael@0 152 if (!obs) {
michael@0 153 return NS_OK;
michael@0 154 }
michael@0 155
michael@0 156 nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData);
michael@0 157 obs->NotifyObservers(message, kSmsReceivedObserverTopic, nullptr);
michael@0 158 return NS_OK;
michael@0 159 }
michael@0 160
michael@0 161 private:
michael@0 162 SmsMessageData mMessageData;
michael@0 163 };
michael@0 164
michael@0 165 // TODO Need to correct the message `threadId` parameter value. Bug 859098
michael@0 166 SmsMessageData message(0, 0, eDeliveryState_Received, eDeliveryStatus_Success,
michael@0 167 nsJNIString(aSender, jenv), EmptyString(),
michael@0 168 nsJNIString(aBody, jenv),
michael@0 169 static_cast<MessageClass>(aMessageClass),
michael@0 170 aTimestamp, false);
michael@0 171
michael@0 172 nsCOMPtr<nsIRunnable> runnable = new NotifySmsReceivedRunnable(message);
michael@0 173 NS_DispatchToMainThread(runnable);
michael@0 174 }
michael@0 175
michael@0 176 NS_EXPORT void JNICALL
michael@0 177 Java_org_mozilla_gecko_GeckoSmsManager_notifySmsSent(JNIEnv* jenv, jclass,
michael@0 178 jint aId,
michael@0 179 jstring aReceiver,
michael@0 180 jstring aBody,
michael@0 181 jlong aTimestamp,
michael@0 182 jint aRequestId)
michael@0 183 {
michael@0 184 class NotifySmsSentRunnable : public nsRunnable {
michael@0 185 public:
michael@0 186 NotifySmsSentRunnable(const SmsMessageData& aMessageData,
michael@0 187 int32_t aRequestId)
michael@0 188 : mMessageData(aMessageData)
michael@0 189 , mRequestId(aRequestId)
michael@0 190 {}
michael@0 191
michael@0 192 NS_IMETHODIMP Run() {
michael@0 193 /*
michael@0 194 * First, we are going to notify all SmsManager that a message has
michael@0 195 * been sent. Then, we will notify the SmsRequest object about it.
michael@0 196 */
michael@0 197 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
michael@0 198 if (!obs) {
michael@0 199 return NS_OK;
michael@0 200 }
michael@0 201
michael@0 202 nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData);
michael@0 203 obs->NotifyObservers(message, kSmsSentObserverTopic, nullptr);
michael@0 204
michael@0 205 nsCOMPtr<nsIMobileMessageCallback> request =
michael@0 206 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId);
michael@0 207 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
michael@0 208
michael@0 209 request->NotifyMessageSent(message);
michael@0 210 return NS_OK;
michael@0 211 }
michael@0 212
michael@0 213 private:
michael@0 214 SmsMessageData mMessageData;
michael@0 215 int32_t mRequestId;
michael@0 216 };
michael@0 217
michael@0 218 // TODO Need to add the message `messageClass` parameter value. Bug 804476
michael@0 219 // TODO Need to correct the message `threadId` parameter value. Bug 859098
michael@0 220 SmsMessageData message(aId, 0, eDeliveryState_Sent, eDeliveryStatus_Pending,
michael@0 221 EmptyString(), nsJNIString(aReceiver, jenv),
michael@0 222 nsJNIString(aBody, jenv), eMessageClass_Normal,
michael@0 223 aTimestamp, true);
michael@0 224
michael@0 225 nsCOMPtr<nsIRunnable> runnable = new NotifySmsSentRunnable(message, aRequestId);
michael@0 226 NS_DispatchToMainThread(runnable);
michael@0 227 }
michael@0 228
michael@0 229 NS_EXPORT void JNICALL
michael@0 230 Java_org_mozilla_gecko_GeckoSmsManager_notifySmsDelivery(JNIEnv* jenv, jclass,
michael@0 231 jint aId,
michael@0 232 jint aDeliveryStatus,
michael@0 233 jstring aReceiver,
michael@0 234 jstring aBody,
michael@0 235 jlong aTimestamp)
michael@0 236 {
michael@0 237 class NotifySmsDeliveredRunnable : public nsRunnable {
michael@0 238 public:
michael@0 239 NotifySmsDeliveredRunnable(const SmsMessageData& aMessageData)
michael@0 240 : mMessageData(aMessageData)
michael@0 241 {}
michael@0 242
michael@0 243 NS_IMETHODIMP Run() {
michael@0 244 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
michael@0 245 if (!obs) {
michael@0 246 return NS_OK;
michael@0 247 }
michael@0 248
michael@0 249 nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData);
michael@0 250 const char* topic = (mMessageData.deliveryStatus() == eDeliveryStatus_Success)
michael@0 251 ? kSmsDeliverySuccessObserverTopic
michael@0 252 : kSmsDeliveryErrorObserverTopic;
michael@0 253 obs->NotifyObservers(message, topic, nullptr);
michael@0 254
michael@0 255 return NS_OK;
michael@0 256 }
michael@0 257
michael@0 258 private:
michael@0 259 SmsMessageData mMessageData;
michael@0 260 };
michael@0 261
michael@0 262 // TODO Need to add the message `messageClass` parameter value. Bug 804476
michael@0 263 // TODO Need to correct the message `threadId` parameter value. Bug 859098
michael@0 264 SmsMessageData message(aId, 0, eDeliveryState_Sent,
michael@0 265 static_cast<DeliveryStatus>(aDeliveryStatus),
michael@0 266 EmptyString(), nsJNIString(aReceiver, jenv),
michael@0 267 nsJNIString(aBody, jenv), eMessageClass_Normal,
michael@0 268 aTimestamp, true);
michael@0 269
michael@0 270 nsCOMPtr<nsIRunnable> runnable = new NotifySmsDeliveredRunnable(message);
michael@0 271 NS_DispatchToMainThread(runnable);
michael@0 272 }
michael@0 273
michael@0 274 NS_EXPORT void JNICALL
michael@0 275 Java_org_mozilla_gecko_GeckoSmsManager_notifySmsSendFailed(JNIEnv* jenv, jclass,
michael@0 276 jint aError,
michael@0 277 jint aRequestId)
michael@0 278 {
michael@0 279 class NotifySmsSendFailedRunnable : public nsRunnable {
michael@0 280 public:
michael@0 281 NotifySmsSendFailedRunnable(int32_t aError,
michael@0 282 int32_t aRequestId)
michael@0 283 : mError(aError)
michael@0 284 , mRequestId(aRequestId)
michael@0 285 {}
michael@0 286
michael@0 287 NS_IMETHODIMP Run() {
michael@0 288 nsCOMPtr<nsIMobileMessageCallback> request =
michael@0 289 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId);
michael@0 290 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
michael@0 291
michael@0 292 request->NotifySendMessageFailed(mError);
michael@0 293 return NS_OK;
michael@0 294 }
michael@0 295
michael@0 296 private:
michael@0 297 int32_t mError;
michael@0 298 int32_t mRequestId;
michael@0 299 };
michael@0 300
michael@0 301
michael@0 302 nsCOMPtr<nsIRunnable> runnable =
michael@0 303 new NotifySmsSendFailedRunnable(aError, aRequestId);
michael@0 304 NS_DispatchToMainThread(runnable);
michael@0 305 }
michael@0 306
michael@0 307 NS_EXPORT void JNICALL
michael@0 308 Java_org_mozilla_gecko_GeckoSmsManager_notifyGetSms(JNIEnv* jenv, jclass,
michael@0 309 jint aId,
michael@0 310 jint aDeliveryStatus,
michael@0 311 jstring aReceiver,
michael@0 312 jstring aSender,
michael@0 313 jstring aBody,
michael@0 314 jlong aTimestamp,
michael@0 315 jint aRequestId)
michael@0 316 {
michael@0 317 class NotifyGetSmsRunnable : public nsRunnable {
michael@0 318 public:
michael@0 319 NotifyGetSmsRunnable(const SmsMessageData& aMessageData,
michael@0 320 int32_t aRequestId)
michael@0 321 : mMessageData(aMessageData)
michael@0 322 , mRequestId(aRequestId)
michael@0 323 {}
michael@0 324
michael@0 325 NS_IMETHODIMP Run() {
michael@0 326 nsCOMPtr<nsIMobileMessageCallback> request =
michael@0 327 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId);
michael@0 328 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
michael@0 329
michael@0 330 nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData);
michael@0 331 request->NotifyMessageGot(message);
michael@0 332 return NS_OK;
michael@0 333 }
michael@0 334
michael@0 335 private:
michael@0 336 SmsMessageData mMessageData;
michael@0 337 int32_t mRequestId;
michael@0 338 };
michael@0 339
michael@0 340 nsJNIString receiver = nsJNIString(aReceiver, jenv);
michael@0 341 DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received
michael@0 342 : eDeliveryState_Sent;
michael@0 343
michael@0 344 // TODO Need to add the message `read` parameter value. Bug 748391
michael@0 345 // TODO Need to add the message `messageClass` parameter value. Bug 804476
michael@0 346 // TODO Need to correct the message `threadId` parameter value. Bug 859098
michael@0 347 SmsMessageData message(aId, 0, state,
michael@0 348 static_cast<DeliveryStatus>(aDeliveryStatus),
michael@0 349 nsJNIString(aSender, jenv), receiver,
michael@0 350 nsJNIString(aBody, jenv), eMessageClass_Normal,
michael@0 351 aTimestamp, true);
michael@0 352
michael@0 353 nsCOMPtr<nsIRunnable> runnable = new NotifyGetSmsRunnable(message, aRequestId);
michael@0 354 NS_DispatchToMainThread(runnable);
michael@0 355 }
michael@0 356
michael@0 357 NS_EXPORT void JNICALL
michael@0 358 Java_org_mozilla_gecko_GeckoSmsManager_notifyGetSmsFailed(JNIEnv* jenv, jclass,
michael@0 359 jint aError,
michael@0 360 jint aRequestId)
michael@0 361 {
michael@0 362 class NotifyGetSmsFailedRunnable : public nsRunnable {
michael@0 363 public:
michael@0 364 NotifyGetSmsFailedRunnable(int32_t aError,
michael@0 365 int32_t aRequestId)
michael@0 366 : mError(aError)
michael@0 367 , mRequestId(aRequestId)
michael@0 368 {}
michael@0 369
michael@0 370 NS_IMETHODIMP Run() {
michael@0 371 nsCOMPtr<nsIMobileMessageCallback> request =
michael@0 372 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId);
michael@0 373 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
michael@0 374
michael@0 375 request->NotifyGetMessageFailed(mError);
michael@0 376 return NS_OK;
michael@0 377 }
michael@0 378
michael@0 379 private:
michael@0 380 int32_t mError;
michael@0 381 int32_t mRequestId;
michael@0 382 };
michael@0 383
michael@0 384
michael@0 385 nsCOMPtr<nsIRunnable> runnable =
michael@0 386 new NotifyGetSmsFailedRunnable(aError, aRequestId);
michael@0 387 NS_DispatchToMainThread(runnable);
michael@0 388 }
michael@0 389
michael@0 390 NS_EXPORT void JNICALL
michael@0 391 Java_org_mozilla_gecko_GeckoSmsManager_notifySmsDeleted(JNIEnv* jenv, jclass,
michael@0 392 jboolean aDeleted,
michael@0 393 jint aRequestId)
michael@0 394 {
michael@0 395 class NotifySmsDeletedRunnable : public nsRunnable {
michael@0 396 public:
michael@0 397 NotifySmsDeletedRunnable(bool aDeleted, int32_t aRequestId)
michael@0 398 : mDeleted(aDeleted)
michael@0 399 , mRequestId(aRequestId)
michael@0 400 {}
michael@0 401
michael@0 402 NS_IMETHODIMP Run() {
michael@0 403 nsCOMPtr<nsIMobileMessageCallback> request =
michael@0 404 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId);
michael@0 405 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
michael@0 406
michael@0 407 // For android, we support only single SMS deletion.
michael@0 408 request->NotifyMessageDeleted(&mDeleted, 1);
michael@0 409 return NS_OK;
michael@0 410 }
michael@0 411
michael@0 412 private:
michael@0 413 bool mDeleted;
michael@0 414 int32_t mRequestId;
michael@0 415 };
michael@0 416
michael@0 417
michael@0 418 nsCOMPtr<nsIRunnable> runnable =
michael@0 419 new NotifySmsDeletedRunnable(aDeleted, aRequestId);
michael@0 420 NS_DispatchToMainThread(runnable);
michael@0 421 }
michael@0 422
michael@0 423 NS_EXPORT void JNICALL
michael@0 424 Java_org_mozilla_gecko_GeckoSmsManager_notifySmsDeleteFailed(JNIEnv* jenv, jclass,
michael@0 425 jint aError,
michael@0 426 jint aRequestId)
michael@0 427 {
michael@0 428 class NotifySmsDeleteFailedRunnable : public nsRunnable {
michael@0 429 public:
michael@0 430 NotifySmsDeleteFailedRunnable(int32_t aError,
michael@0 431 int32_t aRequestId)
michael@0 432 : mError(aError)
michael@0 433 , mRequestId(aRequestId)
michael@0 434 {}
michael@0 435
michael@0 436 NS_IMETHODIMP Run() {
michael@0 437 nsCOMPtr<nsIMobileMessageCallback> request =
michael@0 438 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId);
michael@0 439 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
michael@0 440
michael@0 441 request->NotifyDeleteMessageFailed(mError);
michael@0 442 return NS_OK;
michael@0 443 }
michael@0 444
michael@0 445 private:
michael@0 446 int32_t mError;
michael@0 447 int32_t mRequestId;
michael@0 448 };
michael@0 449
michael@0 450
michael@0 451 nsCOMPtr<nsIRunnable> runnable =
michael@0 452 new NotifySmsDeleteFailedRunnable(aError, aRequestId);
michael@0 453 NS_DispatchToMainThread(runnable);
michael@0 454 }
michael@0 455
michael@0 456 NS_EXPORT void JNICALL
michael@0 457 Java_org_mozilla_gecko_GeckoSmsManager_notifyNoMessageInList(JNIEnv* jenv, jclass,
michael@0 458 jint aRequestId)
michael@0 459 {
michael@0 460 class NotifyNoMessageInListRunnable : public nsRunnable {
michael@0 461 public:
michael@0 462 NotifyNoMessageInListRunnable(int32_t aRequestId)
michael@0 463 : mRequestId(aRequestId)
michael@0 464 {}
michael@0 465
michael@0 466 NS_IMETHODIMP Run() {
michael@0 467 nsCOMPtr<nsIMobileMessageCallback> request =
michael@0 468 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId);
michael@0 469 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
michael@0 470
michael@0 471 request->NotifyNoMessageInList();
michael@0 472 return NS_OK;
michael@0 473 }
michael@0 474
michael@0 475 private:
michael@0 476 int32_t mRequestId;
michael@0 477 };
michael@0 478
michael@0 479
michael@0 480 nsCOMPtr<nsIRunnable> runnable =
michael@0 481 new NotifyNoMessageInListRunnable(aRequestId);
michael@0 482 NS_DispatchToMainThread(runnable);
michael@0 483 }
michael@0 484
michael@0 485 NS_EXPORT void JNICALL
michael@0 486 Java_org_mozilla_gecko_GeckoSmsManager_notifyListCreated(JNIEnv* jenv, jclass,
michael@0 487 jint aListId,
michael@0 488 jint aMessageId,
michael@0 489 jint aDeliveryStatus,
michael@0 490 jstring aReceiver,
michael@0 491 jstring aSender,
michael@0 492 jstring aBody,
michael@0 493 jlong aTimestamp,
michael@0 494 jint aRequestId)
michael@0 495 {
michael@0 496 class NotifyCreateMessageListRunnable : public nsRunnable {
michael@0 497 public:
michael@0 498 NotifyCreateMessageListRunnable(int32_t aListId,
michael@0 499 const SmsMessageData& aMessageData,
michael@0 500 int32_t aRequestId)
michael@0 501 : mListId(aListId)
michael@0 502 , mMessageData(aMessageData)
michael@0 503 , mRequestId(aRequestId)
michael@0 504 {}
michael@0 505
michael@0 506 NS_IMETHODIMP Run() {
michael@0 507 nsCOMPtr<nsIMobileMessageCallback> request =
michael@0 508 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId);
michael@0 509 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
michael@0 510
michael@0 511 nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData);
michael@0 512 request->NotifyMessageListCreated(mListId, message);
michael@0 513 return NS_OK;
michael@0 514 }
michael@0 515
michael@0 516 private:
michael@0 517 int32_t mListId;
michael@0 518 SmsMessageData mMessageData;
michael@0 519 int32_t mRequestId;
michael@0 520 };
michael@0 521
michael@0 522
michael@0 523 nsJNIString receiver = nsJNIString(aReceiver, jenv);
michael@0 524 DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received
michael@0 525 : eDeliveryState_Sent;
michael@0 526
michael@0 527 // TODO Need to add the message `read` parameter value. Bug 748391
michael@0 528 // TODO Need to add the message `messageClass` parameter value. Bug 804476
michael@0 529 // TODO Need to correct the message `threadId` parameter value. Bug 859098
michael@0 530 SmsMessageData message(aMessageId, 0, state,
michael@0 531 static_cast<DeliveryStatus>(aDeliveryStatus),
michael@0 532 nsJNIString(aSender, jenv), receiver,
michael@0 533 nsJNIString(aBody, jenv), eMessageClass_Normal,
michael@0 534 aTimestamp, true);
michael@0 535
michael@0 536 nsCOMPtr<nsIRunnable> runnable =
michael@0 537 new NotifyCreateMessageListRunnable(aListId, message, aRequestId);
michael@0 538 NS_DispatchToMainThread(runnable);
michael@0 539 }
michael@0 540
michael@0 541 NS_EXPORT void JNICALL
michael@0 542 Java_org_mozilla_gecko_GeckoSmsManager_notifyGotNextMessage(JNIEnv* jenv, jclass,
michael@0 543 jint aMessageId,
michael@0 544 jint aDeliveryStatus,
michael@0 545 jstring aReceiver,
michael@0 546 jstring aSender,
michael@0 547 jstring aBody,
michael@0 548 jlong aTimestamp,
michael@0 549 jint aRequestId)
michael@0 550 {
michael@0 551 class NotifyGotNextMessageRunnable : public nsRunnable {
michael@0 552 public:
michael@0 553 NotifyGotNextMessageRunnable(const SmsMessageData& aMessageData,
michael@0 554 int32_t aRequestId)
michael@0 555 : mMessageData(aMessageData)
michael@0 556 , mRequestId(aRequestId)
michael@0 557 {}
michael@0 558
michael@0 559 NS_IMETHODIMP Run() {
michael@0 560 nsCOMPtr<nsIMobileMessageCallback> request =
michael@0 561 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId);
michael@0 562 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
michael@0 563
michael@0 564 nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData);
michael@0 565 request->NotifyNextMessageInListGot(message);
michael@0 566 return NS_OK;
michael@0 567 }
michael@0 568
michael@0 569 private:
michael@0 570 SmsMessageData mMessageData;
michael@0 571 int32_t mRequestId;
michael@0 572 };
michael@0 573
michael@0 574
michael@0 575 nsJNIString receiver = nsJNIString(aReceiver, jenv);
michael@0 576 DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received
michael@0 577 : eDeliveryState_Sent;
michael@0 578
michael@0 579 // TODO Need to add the message `read` parameter value. Bug 748391
michael@0 580 // TODO Need to add the message `messageClass` parameter value. Bug 804476
michael@0 581 // TODO Need to correct the message `threadId` parameter value. Bug 859098
michael@0 582 SmsMessageData message(aMessageId, 0, state,
michael@0 583 static_cast<DeliveryStatus>(aDeliveryStatus),
michael@0 584 nsJNIString(aSender, jenv), receiver,
michael@0 585 nsJNIString(aBody, jenv), eMessageClass_Normal,
michael@0 586 aTimestamp, true);
michael@0 587
michael@0 588 nsCOMPtr<nsIRunnable> runnable =
michael@0 589 new NotifyGotNextMessageRunnable(message, aRequestId);
michael@0 590 NS_DispatchToMainThread(runnable);
michael@0 591 }
michael@0 592
michael@0 593 NS_EXPORT void JNICALL
michael@0 594 Java_org_mozilla_gecko_GeckoSmsManager_notifyReadingMessageListFailed(JNIEnv* jenv, jclass,
michael@0 595 jint aError,
michael@0 596 jint aRequestId)
michael@0 597 {
michael@0 598 class NotifyReadListFailedRunnable : public nsRunnable {
michael@0 599 public:
michael@0 600 NotifyReadListFailedRunnable(int32_t aError,
michael@0 601 int32_t aRequestId)
michael@0 602 : mError(aError)
michael@0 603 , mRequestId(aRequestId)
michael@0 604 {}
michael@0 605
michael@0 606 NS_IMETHODIMP Run() {
michael@0 607 nsCOMPtr<nsIMobileMessageCallback> request =
michael@0 608 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId);
michael@0 609 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
michael@0 610
michael@0 611 request->NotifyReadMessageListFailed(mError);
michael@0 612 return NS_OK;
michael@0 613 }
michael@0 614
michael@0 615 private:
michael@0 616 int32_t mError;
michael@0 617 int32_t mRequestId;
michael@0 618 };
michael@0 619
michael@0 620
michael@0 621 nsCOMPtr<nsIRunnable> runnable =
michael@0 622 new NotifyReadListFailedRunnable(aError, aRequestId);
michael@0 623 NS_DispatchToMainThread(runnable);
michael@0 624 }
michael@0 625
michael@0 626 #endif // MOZ_WEBSMS_BACKEND
michael@0 627
michael@0 628 NS_EXPORT void JNICALL
michael@0 629 Java_org_mozilla_gecko_GeckoAppShell_scheduleComposite(JNIEnv*, jclass)
michael@0 630 {
michael@0 631 nsWindow::ScheduleComposite();
michael@0 632 }
michael@0 633
michael@0 634 NS_EXPORT void JNICALL
michael@0 635 Java_org_mozilla_gecko_GeckoAppShell_scheduleResumeComposition(JNIEnv*, jclass, jint width, jint height)
michael@0 636 {
michael@0 637 nsWindow::ScheduleResumeComposition(width, height);
michael@0 638 }
michael@0 639
michael@0 640 NS_EXPORT float JNICALL
michael@0 641 Java_org_mozilla_gecko_GeckoAppShell_computeRenderIntegrity(JNIEnv*, jclass)
michael@0 642 {
michael@0 643 return nsWindow::ComputeRenderIntegrity();
michael@0 644 }
michael@0 645
michael@0 646 NS_EXPORT void JNICALL
michael@0 647 Java_org_mozilla_gecko_GeckoAppShell_notifyFilePickerResult(JNIEnv* jenv, jclass, jstring filePath, jlong callback)
michael@0 648 {
michael@0 649 class NotifyFilePickerResultRunnable : public nsRunnable {
michael@0 650 public:
michael@0 651 NotifyFilePickerResultRunnable(nsString& fileDir, long callback) :
michael@0 652 mFileDir(fileDir), mCallback(callback) {}
michael@0 653
michael@0 654 NS_IMETHODIMP Run() {
michael@0 655 nsFilePickerCallback* handler = (nsFilePickerCallback*)mCallback;
michael@0 656 handler->handleResult(mFileDir);
michael@0 657 handler->Release();
michael@0 658 return NS_OK;
michael@0 659 }
michael@0 660 private:
michael@0 661 nsString mFileDir;
michael@0 662 long mCallback;
michael@0 663 };
michael@0 664 nsString path = nsJNIString(filePath, jenv);
michael@0 665
michael@0 666 nsCOMPtr<nsIRunnable> runnable =
michael@0 667 new NotifyFilePickerResultRunnable(path, (long)callback);
michael@0 668 NS_DispatchToMainThread(runnable);
michael@0 669 }
michael@0 670
michael@0 671 static int
michael@0 672 NextPowerOfTwo(int value) {
michael@0 673 // code taken from http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.html
michael@0 674 if (0 == value--) {
michael@0 675 return 1;
michael@0 676 }
michael@0 677 value = (value >> 1) | value;
michael@0 678 value = (value >> 2) | value;
michael@0 679 value = (value >> 4) | value;
michael@0 680 value = (value >> 8) | value;
michael@0 681 value = (value >> 16) | value;
michael@0 682 return value + 1;
michael@0 683 }
michael@0 684
michael@0 685 #define MAX_LOCK_ATTEMPTS 10
michael@0 686
michael@0 687 static bool LockWindowWithRetry(void* window, unsigned char** bits, int* width, int* height, int* format, int* stride)
michael@0 688 {
michael@0 689 int count = 0;
michael@0 690
michael@0 691 while (count < MAX_LOCK_ATTEMPTS) {
michael@0 692 if (AndroidBridge::Bridge()->LockWindow(window, bits, width, height, format, stride))
michael@0 693 return true;
michael@0 694
michael@0 695 count++;
michael@0 696 usleep(500);
michael@0 697 }
michael@0 698
michael@0 699 return false;
michael@0 700 }
michael@0 701
michael@0 702 NS_EXPORT jobject JNICALL
michael@0 703 Java_org_mozilla_gecko_GeckoAppShell_getSurfaceBits(JNIEnv* jenv, jclass, jobject surface)
michael@0 704 {
michael@0 705 static jclass jSurfaceBitsClass = nullptr;
michael@0 706 static jmethodID jSurfaceBitsCtor = 0;
michael@0 707 static jfieldID jSurfaceBitsWidth, jSurfaceBitsHeight, jSurfaceBitsFormat, jSurfaceBitsBuffer;
michael@0 708
michael@0 709 jobject surfaceBits = nullptr;
michael@0 710 unsigned char* bitsCopy = nullptr;
michael@0 711 int dstWidth, dstHeight, dstSize;
michael@0 712
michael@0 713 void* window = AndroidBridge::Bridge()->AcquireNativeWindow(jenv, surface);
michael@0 714 if (!window)
michael@0 715 return nullptr;
michael@0 716
michael@0 717 unsigned char* bits;
michael@0 718 int srcWidth, srcHeight, format, srcStride;
michael@0 719
michael@0 720 // So we lock/unlock once here in order to get whatever is currently the front buffer. It sucks.
michael@0 721 if (!LockWindowWithRetry(window, &bits, &srcWidth, &srcHeight, &format, &srcStride))
michael@0 722 return nullptr;
michael@0 723
michael@0 724 AndroidBridge::Bridge()->UnlockWindow(window);
michael@0 725
michael@0 726 // This is lock will result in the front buffer, since the last unlock rotated it to the back. Probably.
michael@0 727 if (!LockWindowWithRetry(window, &bits, &srcWidth, &srcHeight, &format, &srcStride))
michael@0 728 return nullptr;
michael@0 729
michael@0 730 // These are from android.graphics.PixelFormat
michael@0 731 int bpp;
michael@0 732 switch (format) {
michael@0 733 case 1: // RGBA_8888
michael@0 734 bpp = 4;
michael@0 735 break;
michael@0 736 case 4: // RGB_565
michael@0 737 bpp = 2;
michael@0 738 break;
michael@0 739 default:
michael@0 740 goto cleanup;
michael@0 741 }
michael@0 742
michael@0 743 dstWidth = NextPowerOfTwo(srcWidth);
michael@0 744 dstHeight = NextPowerOfTwo(srcHeight);
michael@0 745 dstSize = dstWidth * dstHeight * bpp;
michael@0 746
michael@0 747 bitsCopy = (unsigned char*)malloc(dstSize);
michael@0 748 bzero(bitsCopy, dstSize);
michael@0 749 for (int i = 0; i < srcHeight; i++) {
michael@0 750 memcpy(bitsCopy + ((dstHeight - i - 1) * dstWidth * bpp), bits + (i * srcStride * bpp), srcStride * bpp);
michael@0 751 }
michael@0 752
michael@0 753 if (!jSurfaceBitsClass) {
michael@0 754 jSurfaceBitsClass = (jclass)jenv->NewGlobalRef(jenv->FindClass("org/mozilla/gecko/SurfaceBits"));
michael@0 755 jSurfaceBitsCtor = jenv->GetMethodID(jSurfaceBitsClass, "<init>", "()V");
michael@0 756
michael@0 757 jSurfaceBitsWidth = jenv->GetFieldID(jSurfaceBitsClass, "width", "I");
michael@0 758 jSurfaceBitsHeight = jenv->GetFieldID(jSurfaceBitsClass, "height", "I");
michael@0 759 jSurfaceBitsFormat = jenv->GetFieldID(jSurfaceBitsClass, "format", "I");
michael@0 760 jSurfaceBitsBuffer = jenv->GetFieldID(jSurfaceBitsClass, "buffer", "Ljava/nio/ByteBuffer;");
michael@0 761 }
michael@0 762
michael@0 763 surfaceBits = jenv->NewObject(jSurfaceBitsClass, jSurfaceBitsCtor);
michael@0 764 jenv->SetIntField(surfaceBits, jSurfaceBitsWidth, dstWidth);
michael@0 765 jenv->SetIntField(surfaceBits, jSurfaceBitsHeight, dstHeight);
michael@0 766 jenv->SetIntField(surfaceBits, jSurfaceBitsFormat, format);
michael@0 767 jenv->SetObjectField(surfaceBits, jSurfaceBitsBuffer, jenv->NewDirectByteBuffer(bitsCopy, dstSize));
michael@0 768
michael@0 769 cleanup:
michael@0 770 AndroidBridge::Bridge()->UnlockWindow(window);
michael@0 771 AndroidBridge::Bridge()->ReleaseNativeWindow(window);
michael@0 772
michael@0 773 return surfaceBits;
michael@0 774 }
michael@0 775
michael@0 776 NS_EXPORT void JNICALL
michael@0 777 Java_org_mozilla_gecko_GeckoAppShell_onFullScreenPluginHidden(JNIEnv* jenv, jclass, jobject view)
michael@0 778 {
michael@0 779 class ExitFullScreenRunnable : public nsRunnable {
michael@0 780 public:
michael@0 781 ExitFullScreenRunnable(jobject view) : mView(view) {}
michael@0 782
michael@0 783 NS_IMETHODIMP Run() {
michael@0 784 JNIEnv* env = AndroidBridge::GetJNIEnv();
michael@0 785 nsPluginInstanceOwner::ExitFullScreen(mView);
michael@0 786 env->DeleteGlobalRef(mView);
michael@0 787 return NS_OK;
michael@0 788 }
michael@0 789
michael@0 790 private:
michael@0 791 jobject mView;
michael@0 792 };
michael@0 793
michael@0 794 nsCOMPtr<nsIRunnable> runnable = new ExitFullScreenRunnable(jenv->NewGlobalRef(view));
michael@0 795 NS_DispatchToMainThread(runnable);
michael@0 796 }
michael@0 797
michael@0 798 NS_EXPORT jobject JNICALL
michael@0 799 Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue(JNIEnv* jenv, jclass, jobject queue)
michael@0 800 {
michael@0 801 static jclass jMessageQueueCls = nullptr;
michael@0 802 static jfieldID jMessagesField;
michael@0 803 static jmethodID jNextMethod;
michael@0 804 if (!jMessageQueueCls) {
michael@0 805 jMessageQueueCls = (jclass) jenv->NewGlobalRef(jenv->FindClass("android/os/MessageQueue"));
michael@0 806 jNextMethod = jenv->GetMethodID(jMessageQueueCls, "next", "()Landroid/os/Message;");
michael@0 807 jMessagesField = jenv->GetFieldID(jMessageQueueCls, "mMessages", "Landroid/os/Message;");
michael@0 808 }
michael@0 809
michael@0 810 if (!jMessageQueueCls || !jNextMethod)
michael@0 811 return nullptr;
michael@0 812
michael@0 813 if (jMessagesField) {
michael@0 814 jobject msg = jenv->GetObjectField(queue, jMessagesField);
michael@0 815 // if queue.mMessages is null, queue.next() will block, which we don't want
michael@0 816 // It turns out to be an order of magnitude more performant to do this extra check here and
michael@0 817 // block less vs. one fewer checks here and more blocking.
michael@0 818 if (!msg) {
michael@0 819 return nullptr;
michael@0 820 }
michael@0 821 }
michael@0 822 return jenv->CallObjectMethod(queue, jNextMethod);
michael@0 823 }
michael@0 824
michael@0 825 NS_EXPORT void JNICALL
michael@0 826 Java_org_mozilla_gecko_GeckoAppShell_onSurfaceTextureFrameAvailable(JNIEnv* jenv, jclass, jobject surfaceTexture, jint id)
michael@0 827 {
michael@0 828 nsSurfaceTexture* st = nsSurfaceTexture::Find(id);
michael@0 829 if (!st) {
michael@0 830 __android_log_print(ANDROID_LOG_ERROR, "GeckoJNI", "Failed to find nsSurfaceTexture with id %d", id);
michael@0 831 return;
michael@0 832 }
michael@0 833
michael@0 834 st->NotifyFrameAvailable();
michael@0 835 }
michael@0 836
michael@0 837 NS_EXPORT void JNICALL
michael@0 838 Java_org_mozilla_gecko_GeckoAppShell_dispatchMemoryPressure(JNIEnv* jenv, jclass)
michael@0 839 {
michael@0 840 NS_DispatchMemoryPressure(MemPressure_New);
michael@0 841 }
michael@0 842
michael@0 843 NS_EXPORT jdouble JNICALL
michael@0 844 Java_org_mozilla_gecko_GeckoJavaSampler_getProfilerTime(JNIEnv *jenv, jclass jc)
michael@0 845 {
michael@0 846 return profiler_time();
michael@0 847 }
michael@0 848
michael@0 849 NS_EXPORT void JNICALL
michael@0 850 Java_org_mozilla_gecko_gfx_NativePanZoomController_abortAnimation(JNIEnv* env, jobject instance)
michael@0 851 {
michael@0 852 APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
michael@0 853 if (controller) {
michael@0 854 // TODO: Pass in correct values for presShellId and viewId.
michael@0 855 controller->CancelAnimation(ScrollableLayerGuid(nsWindow::RootLayerTreeId(), 0, 0));
michael@0 856 }
michael@0 857 }
michael@0 858
michael@0 859 NS_EXPORT void JNICALL
michael@0 860 Java_org_mozilla_gecko_gfx_NativePanZoomController_init(JNIEnv* env, jobject instance)
michael@0 861 {
michael@0 862 if (!AndroidBridge::Bridge()) {
michael@0 863 return;
michael@0 864 }
michael@0 865
michael@0 866 NativePanZoomController* oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(instance);
michael@0 867 if (oldRef && !oldRef->isNull()) {
michael@0 868 MOZ_ASSERT(false, "Registering a new NPZC when we already have one");
michael@0 869 delete oldRef;
michael@0 870 }
michael@0 871 }
michael@0 872
michael@0 873 NS_EXPORT void JNICALL
michael@0 874 Java_org_mozilla_gecko_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, jobject instance, jobject event)
michael@0 875 {
michael@0 876 APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
michael@0 877 if (controller) {
michael@0 878 AndroidGeckoEvent* wrapper = AndroidGeckoEvent::MakeFromJavaObject(env, event);
michael@0 879 const MultiTouchInput& input = wrapper->MakeMultiTouchInput(nsWindow::TopWindow());
michael@0 880 delete wrapper;
michael@0 881 if (input.mType >= 0) {
michael@0 882 controller->ReceiveInputEvent(input, nullptr);
michael@0 883 }
michael@0 884 }
michael@0 885 }
michael@0 886
michael@0 887 NS_EXPORT void JNICALL
michael@0 888 Java_org_mozilla_gecko_gfx_NativePanZoomController_handleMotionEvent(JNIEnv* env, jobject instance, jobject event)
michael@0 889 {
michael@0 890 // FIXME implement this
michael@0 891 }
michael@0 892
michael@0 893 NS_EXPORT jlong JNICALL
michael@0 894 Java_org_mozilla_gecko_gfx_NativePanZoomController_runDelayedCallback(JNIEnv* env, jobject instance)
michael@0 895 {
michael@0 896 if (!AndroidBridge::Bridge()) {
michael@0 897 return -1;
michael@0 898 }
michael@0 899
michael@0 900 return AndroidBridge::Bridge()->RunDelayedTasks();
michael@0 901 }
michael@0 902
michael@0 903 NS_EXPORT void JNICALL
michael@0 904 Java_org_mozilla_gecko_gfx_NativePanZoomController_destroy(JNIEnv* env, jobject instance)
michael@0 905 {
michael@0 906 if (!AndroidBridge::Bridge()) {
michael@0 907 return;
michael@0 908 }
michael@0 909
michael@0 910 NativePanZoomController* oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(nullptr);
michael@0 911 if (!oldRef || oldRef->isNull()) {
michael@0 912 MOZ_ASSERT(false, "Clearing a non-existent NPZC");
michael@0 913 } else {
michael@0 914 delete oldRef;
michael@0 915 }
michael@0 916 }
michael@0 917
michael@0 918 NS_EXPORT void JNICALL
michael@0 919 Java_org_mozilla_gecko_gfx_NativePanZoomController_notifyDefaultActionPrevented(JNIEnv* env, jobject instance, jboolean prevented)
michael@0 920 {
michael@0 921 APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
michael@0 922 if (controller) {
michael@0 923 // TODO: Pass in correct values for presShellId and viewId.
michael@0 924 controller->ContentReceivedTouch(ScrollableLayerGuid(nsWindow::RootLayerTreeId(), 0, 0), prevented);
michael@0 925 }
michael@0 926 }
michael@0 927
michael@0 928 NS_EXPORT jboolean JNICALL
michael@0 929 Java_org_mozilla_gecko_gfx_NativePanZoomController_getRedrawHint(JNIEnv* env, jobject instance)
michael@0 930 {
michael@0 931 // FIXME implement this
michael@0 932 return true;
michael@0 933 }
michael@0 934
michael@0 935 NS_EXPORT void JNICALL
michael@0 936 Java_org_mozilla_gecko_gfx_NativePanZoomController_setOverScrollMode(JNIEnv* env, jobject instance, jint overscrollMode)
michael@0 937 {
michael@0 938 // FIXME implement this
michael@0 939 }
michael@0 940
michael@0 941 NS_EXPORT jint JNICALL
michael@0 942 Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode(JNIEnv* env, jobject instance)
michael@0 943 {
michael@0 944 // FIXME implement this
michael@0 945 return 0;
michael@0 946 }
michael@0 947
michael@0 948 NS_EXPORT jboolean JNICALL
michael@0 949 Java_org_mozilla_gecko_ANRReporter_requestNativeStack(JNIEnv*, jclass, jboolean aUnwind)
michael@0 950 {
michael@0 951 if (profiler_is_active()) {
michael@0 952 // Don't proceed if profiler is already running
michael@0 953 return JNI_FALSE;
michael@0 954 }
michael@0 955 // WARNING: we are on the ANR reporter thread at this point and it is
michael@0 956 // generally unsafe to use the profiler from off the main thread. However,
michael@0 957 // the risk here is limited because for most users, the profiler is not run
michael@0 958 // elsewhere. See the discussion in Bug 863777, comment 13
michael@0 959 const char *NATIVE_STACK_FEATURES[] =
michael@0 960 {"leaf", "threads", "privacy"};
michael@0 961 const char *NATIVE_STACK_UNWIND_FEATURES[] =
michael@0 962 {"leaf", "threads", "privacy", "stackwalk"};
michael@0 963
michael@0 964 const char **features = NATIVE_STACK_FEATURES;
michael@0 965 size_t features_size = sizeof(NATIVE_STACK_FEATURES);
michael@0 966 if (aUnwind) {
michael@0 967 features = NATIVE_STACK_UNWIND_FEATURES;
michael@0 968 features_size = sizeof(NATIVE_STACK_UNWIND_FEATURES);
michael@0 969 // We want the new unwinder if the unwind mode has not been set yet
michael@0 970 putenv("MOZ_PROFILER_NEW=1");
michael@0 971 }
michael@0 972
michael@0 973 const char *NATIVE_STACK_THREADS[] =
michael@0 974 {"GeckoMain", "Compositor"};
michael@0 975 // Buffer one sample and let the profiler wait a long time
michael@0 976 profiler_start(100, 10000, features, features_size / sizeof(char*),
michael@0 977 NATIVE_STACK_THREADS, sizeof(NATIVE_STACK_THREADS) / sizeof(char*));
michael@0 978 return JNI_TRUE;
michael@0 979 }
michael@0 980
michael@0 981 NS_EXPORT jstring JNICALL
michael@0 982 Java_org_mozilla_gecko_ANRReporter_getNativeStack(JNIEnv* jenv, jclass)
michael@0 983 {
michael@0 984 if (!profiler_is_active()) {
michael@0 985 // Maybe profiler support is disabled?
michael@0 986 return nullptr;
michael@0 987 }
michael@0 988 char *profile = profiler_get_profile();
michael@0 989 while (profile && !strlen(profile)) {
michael@0 990 // no sample yet?
michael@0 991 sched_yield();
michael@0 992 profile = profiler_get_profile();
michael@0 993 }
michael@0 994 jstring result = nullptr;
michael@0 995 if (profile) {
michael@0 996 result = jenv->NewStringUTF(profile);
michael@0 997 free(profile);
michael@0 998 }
michael@0 999 return result;
michael@0 1000 }
michael@0 1001
michael@0 1002 NS_EXPORT void JNICALL
michael@0 1003 Java_org_mozilla_gecko_ANRReporter_releaseNativeStack(JNIEnv* jenv, jclass)
michael@0 1004 {
michael@0 1005 if (!profiler_is_active()) {
michael@0 1006 // Maybe profiler support is disabled?
michael@0 1007 return;
michael@0 1008 }
michael@0 1009 mozilla_sampler_stop();
michael@0 1010 }
michael@0 1011
michael@0 1012 }

mercurial