widget/android/AndroidJNI.cpp

changeset 0
6474c204b198
     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 +}

mercurial