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

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

mercurial