|
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/. */ |
|
5 |
|
6 #include "mozilla/Hal.h" |
|
7 #include "nsIFile.h" |
|
8 #include "nsString.h" |
|
9 |
|
10 #include "AndroidBridge.h" |
|
11 #include "AndroidGraphicBuffer.h" |
|
12 |
|
13 #include <jni.h> |
|
14 #include <pthread.h> |
|
15 #include <dlfcn.h> |
|
16 #include <stdio.h> |
|
17 #include <unistd.h> |
|
18 #include <sched.h> |
|
19 |
|
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" |
|
26 |
|
27 #ifdef MOZ_CRASHREPORTER |
|
28 #include "nsICrashReporter.h" |
|
29 #include "nsExceptionHandler.h" |
|
30 #endif |
|
31 |
|
32 #include "mozilla/unused.h" |
|
33 |
|
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" |
|
45 |
|
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; |
|
51 |
|
52 /* Forward declare all the JNI methods as extern "C" */ |
|
53 |
|
54 extern "C" { |
|
55 /* |
|
56 * Incoming JNI methods |
|
57 */ |
|
58 |
|
59 NS_EXPORT void JNICALL |
|
60 Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv *jenv, jclass jc) |
|
61 { |
|
62 AndroidBridge::ConstructBridge(jenv); |
|
63 } |
|
64 |
|
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 } |
|
72 |
|
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 } |
|
80 |
|
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 } |
|
86 |
|
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 } |
|
93 |
|
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 |
|
102 |
|
103 abort(); |
|
104 } |
|
105 |
|
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 {} |
|
119 |
|
120 NS_IMETHODIMP Run() { |
|
121 hal::NotifyBatteryChange(hal::BatteryInformation(mLevel, mCharging, mRemainingTime)); |
|
122 return NS_OK; |
|
123 } |
|
124 |
|
125 private: |
|
126 double mLevel; |
|
127 bool mCharging; |
|
128 double mRemainingTime; |
|
129 }; |
|
130 |
|
131 nsCOMPtr<nsIRunnable> runnable = new NotifyBatteryChangeRunnable(aLevel, aCharging, aRemainingTime); |
|
132 NS_DispatchToMainThread(runnable); |
|
133 } |
|
134 |
|
135 #ifdef MOZ_WEBSMS_BACKEND |
|
136 |
|
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 {} |
|
149 |
|
150 NS_IMETHODIMP Run() { |
|
151 nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
|
152 if (!obs) { |
|
153 return NS_OK; |
|
154 } |
|
155 |
|
156 nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData); |
|
157 obs->NotifyObservers(message, kSmsReceivedObserverTopic, nullptr); |
|
158 return NS_OK; |
|
159 } |
|
160 |
|
161 private: |
|
162 SmsMessageData mMessageData; |
|
163 }; |
|
164 |
|
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); |
|
171 |
|
172 nsCOMPtr<nsIRunnable> runnable = new NotifySmsReceivedRunnable(message); |
|
173 NS_DispatchToMainThread(runnable); |
|
174 } |
|
175 |
|
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 {} |
|
191 |
|
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 } |
|
201 |
|
202 nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData); |
|
203 obs->NotifyObservers(message, kSmsSentObserverTopic, nullptr); |
|
204 |
|
205 nsCOMPtr<nsIMobileMessageCallback> request = |
|
206 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); |
|
207 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); |
|
208 |
|
209 request->NotifyMessageSent(message); |
|
210 return NS_OK; |
|
211 } |
|
212 |
|
213 private: |
|
214 SmsMessageData mMessageData; |
|
215 int32_t mRequestId; |
|
216 }; |
|
217 |
|
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); |
|
224 |
|
225 nsCOMPtr<nsIRunnable> runnable = new NotifySmsSentRunnable(message, aRequestId); |
|
226 NS_DispatchToMainThread(runnable); |
|
227 } |
|
228 |
|
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 {} |
|
242 |
|
243 NS_IMETHODIMP Run() { |
|
244 nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
|
245 if (!obs) { |
|
246 return NS_OK; |
|
247 } |
|
248 |
|
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); |
|
254 |
|
255 return NS_OK; |
|
256 } |
|
257 |
|
258 private: |
|
259 SmsMessageData mMessageData; |
|
260 }; |
|
261 |
|
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); |
|
269 |
|
270 nsCOMPtr<nsIRunnable> runnable = new NotifySmsDeliveredRunnable(message); |
|
271 NS_DispatchToMainThread(runnable); |
|
272 } |
|
273 |
|
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 {} |
|
286 |
|
287 NS_IMETHODIMP Run() { |
|
288 nsCOMPtr<nsIMobileMessageCallback> request = |
|
289 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); |
|
290 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); |
|
291 |
|
292 request->NotifySendMessageFailed(mError); |
|
293 return NS_OK; |
|
294 } |
|
295 |
|
296 private: |
|
297 int32_t mError; |
|
298 int32_t mRequestId; |
|
299 }; |
|
300 |
|
301 |
|
302 nsCOMPtr<nsIRunnable> runnable = |
|
303 new NotifySmsSendFailedRunnable(aError, aRequestId); |
|
304 NS_DispatchToMainThread(runnable); |
|
305 } |
|
306 |
|
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 {} |
|
324 |
|
325 NS_IMETHODIMP Run() { |
|
326 nsCOMPtr<nsIMobileMessageCallback> request = |
|
327 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); |
|
328 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); |
|
329 |
|
330 nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData); |
|
331 request->NotifyMessageGot(message); |
|
332 return NS_OK; |
|
333 } |
|
334 |
|
335 private: |
|
336 SmsMessageData mMessageData; |
|
337 int32_t mRequestId; |
|
338 }; |
|
339 |
|
340 nsJNIString receiver = nsJNIString(aReceiver, jenv); |
|
341 DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received |
|
342 : eDeliveryState_Sent; |
|
343 |
|
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); |
|
352 |
|
353 nsCOMPtr<nsIRunnable> runnable = new NotifyGetSmsRunnable(message, aRequestId); |
|
354 NS_DispatchToMainThread(runnable); |
|
355 } |
|
356 |
|
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 {} |
|
369 |
|
370 NS_IMETHODIMP Run() { |
|
371 nsCOMPtr<nsIMobileMessageCallback> request = |
|
372 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); |
|
373 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); |
|
374 |
|
375 request->NotifyGetMessageFailed(mError); |
|
376 return NS_OK; |
|
377 } |
|
378 |
|
379 private: |
|
380 int32_t mError; |
|
381 int32_t mRequestId; |
|
382 }; |
|
383 |
|
384 |
|
385 nsCOMPtr<nsIRunnable> runnable = |
|
386 new NotifyGetSmsFailedRunnable(aError, aRequestId); |
|
387 NS_DispatchToMainThread(runnable); |
|
388 } |
|
389 |
|
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 {} |
|
401 |
|
402 NS_IMETHODIMP Run() { |
|
403 nsCOMPtr<nsIMobileMessageCallback> request = |
|
404 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); |
|
405 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); |
|
406 |
|
407 // For android, we support only single SMS deletion. |
|
408 request->NotifyMessageDeleted(&mDeleted, 1); |
|
409 return NS_OK; |
|
410 } |
|
411 |
|
412 private: |
|
413 bool mDeleted; |
|
414 int32_t mRequestId; |
|
415 }; |
|
416 |
|
417 |
|
418 nsCOMPtr<nsIRunnable> runnable = |
|
419 new NotifySmsDeletedRunnable(aDeleted, aRequestId); |
|
420 NS_DispatchToMainThread(runnable); |
|
421 } |
|
422 |
|
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 {} |
|
435 |
|
436 NS_IMETHODIMP Run() { |
|
437 nsCOMPtr<nsIMobileMessageCallback> request = |
|
438 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); |
|
439 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); |
|
440 |
|
441 request->NotifyDeleteMessageFailed(mError); |
|
442 return NS_OK; |
|
443 } |
|
444 |
|
445 private: |
|
446 int32_t mError; |
|
447 int32_t mRequestId; |
|
448 }; |
|
449 |
|
450 |
|
451 nsCOMPtr<nsIRunnable> runnable = |
|
452 new NotifySmsDeleteFailedRunnable(aError, aRequestId); |
|
453 NS_DispatchToMainThread(runnable); |
|
454 } |
|
455 |
|
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 {} |
|
465 |
|
466 NS_IMETHODIMP Run() { |
|
467 nsCOMPtr<nsIMobileMessageCallback> request = |
|
468 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); |
|
469 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); |
|
470 |
|
471 request->NotifyNoMessageInList(); |
|
472 return NS_OK; |
|
473 } |
|
474 |
|
475 private: |
|
476 int32_t mRequestId; |
|
477 }; |
|
478 |
|
479 |
|
480 nsCOMPtr<nsIRunnable> runnable = |
|
481 new NotifyNoMessageInListRunnable(aRequestId); |
|
482 NS_DispatchToMainThread(runnable); |
|
483 } |
|
484 |
|
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 {} |
|
505 |
|
506 NS_IMETHODIMP Run() { |
|
507 nsCOMPtr<nsIMobileMessageCallback> request = |
|
508 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); |
|
509 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); |
|
510 |
|
511 nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData); |
|
512 request->NotifyMessageListCreated(mListId, message); |
|
513 return NS_OK; |
|
514 } |
|
515 |
|
516 private: |
|
517 int32_t mListId; |
|
518 SmsMessageData mMessageData; |
|
519 int32_t mRequestId; |
|
520 }; |
|
521 |
|
522 |
|
523 nsJNIString receiver = nsJNIString(aReceiver, jenv); |
|
524 DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received |
|
525 : eDeliveryState_Sent; |
|
526 |
|
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); |
|
535 |
|
536 nsCOMPtr<nsIRunnable> runnable = |
|
537 new NotifyCreateMessageListRunnable(aListId, message, aRequestId); |
|
538 NS_DispatchToMainThread(runnable); |
|
539 } |
|
540 |
|
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 {} |
|
558 |
|
559 NS_IMETHODIMP Run() { |
|
560 nsCOMPtr<nsIMobileMessageCallback> request = |
|
561 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); |
|
562 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); |
|
563 |
|
564 nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData); |
|
565 request->NotifyNextMessageInListGot(message); |
|
566 return NS_OK; |
|
567 } |
|
568 |
|
569 private: |
|
570 SmsMessageData mMessageData; |
|
571 int32_t mRequestId; |
|
572 }; |
|
573 |
|
574 |
|
575 nsJNIString receiver = nsJNIString(aReceiver, jenv); |
|
576 DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received |
|
577 : eDeliveryState_Sent; |
|
578 |
|
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); |
|
587 |
|
588 nsCOMPtr<nsIRunnable> runnable = |
|
589 new NotifyGotNextMessageRunnable(message, aRequestId); |
|
590 NS_DispatchToMainThread(runnable); |
|
591 } |
|
592 |
|
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 {} |
|
605 |
|
606 NS_IMETHODIMP Run() { |
|
607 nsCOMPtr<nsIMobileMessageCallback> request = |
|
608 AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); |
|
609 NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); |
|
610 |
|
611 request->NotifyReadMessageListFailed(mError); |
|
612 return NS_OK; |
|
613 } |
|
614 |
|
615 private: |
|
616 int32_t mError; |
|
617 int32_t mRequestId; |
|
618 }; |
|
619 |
|
620 |
|
621 nsCOMPtr<nsIRunnable> runnable = |
|
622 new NotifyReadListFailedRunnable(aError, aRequestId); |
|
623 NS_DispatchToMainThread(runnable); |
|
624 } |
|
625 |
|
626 #endif // MOZ_WEBSMS_BACKEND |
|
627 |
|
628 NS_EXPORT void JNICALL |
|
629 Java_org_mozilla_gecko_GeckoAppShell_scheduleComposite(JNIEnv*, jclass) |
|
630 { |
|
631 nsWindow::ScheduleComposite(); |
|
632 } |
|
633 |
|
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 } |
|
639 |
|
640 NS_EXPORT float JNICALL |
|
641 Java_org_mozilla_gecko_GeckoAppShell_computeRenderIntegrity(JNIEnv*, jclass) |
|
642 { |
|
643 return nsWindow::ComputeRenderIntegrity(); |
|
644 } |
|
645 |
|
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) {} |
|
653 |
|
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); |
|
665 |
|
666 nsCOMPtr<nsIRunnable> runnable = |
|
667 new NotifyFilePickerResultRunnable(path, (long)callback); |
|
668 NS_DispatchToMainThread(runnable); |
|
669 } |
|
670 |
|
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 } |
|
684 |
|
685 #define MAX_LOCK_ATTEMPTS 10 |
|
686 |
|
687 static bool LockWindowWithRetry(void* window, unsigned char** bits, int* width, int* height, int* format, int* stride) |
|
688 { |
|
689 int count = 0; |
|
690 |
|
691 while (count < MAX_LOCK_ATTEMPTS) { |
|
692 if (AndroidBridge::Bridge()->LockWindow(window, bits, width, height, format, stride)) |
|
693 return true; |
|
694 |
|
695 count++; |
|
696 usleep(500); |
|
697 } |
|
698 |
|
699 return false; |
|
700 } |
|
701 |
|
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; |
|
708 |
|
709 jobject surfaceBits = nullptr; |
|
710 unsigned char* bitsCopy = nullptr; |
|
711 int dstWidth, dstHeight, dstSize; |
|
712 |
|
713 void* window = AndroidBridge::Bridge()->AcquireNativeWindow(jenv, surface); |
|
714 if (!window) |
|
715 return nullptr; |
|
716 |
|
717 unsigned char* bits; |
|
718 int srcWidth, srcHeight, format, srcStride; |
|
719 |
|
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; |
|
723 |
|
724 AndroidBridge::Bridge()->UnlockWindow(window); |
|
725 |
|
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; |
|
729 |
|
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 } |
|
742 |
|
743 dstWidth = NextPowerOfTwo(srcWidth); |
|
744 dstHeight = NextPowerOfTwo(srcHeight); |
|
745 dstSize = dstWidth * dstHeight * bpp; |
|
746 |
|
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 } |
|
752 |
|
753 if (!jSurfaceBitsClass) { |
|
754 jSurfaceBitsClass = (jclass)jenv->NewGlobalRef(jenv->FindClass("org/mozilla/gecko/SurfaceBits")); |
|
755 jSurfaceBitsCtor = jenv->GetMethodID(jSurfaceBitsClass, "<init>", "()V"); |
|
756 |
|
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 } |
|
762 |
|
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)); |
|
768 |
|
769 cleanup: |
|
770 AndroidBridge::Bridge()->UnlockWindow(window); |
|
771 AndroidBridge::Bridge()->ReleaseNativeWindow(window); |
|
772 |
|
773 return surfaceBits; |
|
774 } |
|
775 |
|
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) {} |
|
782 |
|
783 NS_IMETHODIMP Run() { |
|
784 JNIEnv* env = AndroidBridge::GetJNIEnv(); |
|
785 nsPluginInstanceOwner::ExitFullScreen(mView); |
|
786 env->DeleteGlobalRef(mView); |
|
787 return NS_OK; |
|
788 } |
|
789 |
|
790 private: |
|
791 jobject mView; |
|
792 }; |
|
793 |
|
794 nsCOMPtr<nsIRunnable> runnable = new ExitFullScreenRunnable(jenv->NewGlobalRef(view)); |
|
795 NS_DispatchToMainThread(runnable); |
|
796 } |
|
797 |
|
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 } |
|
809 |
|
810 if (!jMessageQueueCls || !jNextMethod) |
|
811 return nullptr; |
|
812 |
|
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 } |
|
824 |
|
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 } |
|
833 |
|
834 st->NotifyFrameAvailable(); |
|
835 } |
|
836 |
|
837 NS_EXPORT void JNICALL |
|
838 Java_org_mozilla_gecko_GeckoAppShell_dispatchMemoryPressure(JNIEnv* jenv, jclass) |
|
839 { |
|
840 NS_DispatchMemoryPressure(MemPressure_New); |
|
841 } |
|
842 |
|
843 NS_EXPORT jdouble JNICALL |
|
844 Java_org_mozilla_gecko_GeckoJavaSampler_getProfilerTime(JNIEnv *jenv, jclass jc) |
|
845 { |
|
846 return profiler_time(); |
|
847 } |
|
848 |
|
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 } |
|
858 |
|
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 } |
|
865 |
|
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 } |
|
872 |
|
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 } |
|
886 |
|
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 } |
|
892 |
|
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 } |
|
899 |
|
900 return AndroidBridge::Bridge()->RunDelayedTasks(); |
|
901 } |
|
902 |
|
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 } |
|
909 |
|
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 } |
|
917 |
|
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 } |
|
927 |
|
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 } |
|
934 |
|
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 } |
|
940 |
|
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 } |
|
947 |
|
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"}; |
|
963 |
|
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 } |
|
972 |
|
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 } |
|
980 |
|
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; |
|
1000 } |
|
1001 |
|
1002 NS_EXPORT void JNICALL |
|
1003 Java_org_mozilla_gecko_ANRReporter_releaseNativeStack(JNIEnv* jenv, jclass) |
|
1004 { |
|
1005 if (!profiler_is_active()) { |
|
1006 // Maybe profiler support is disabled? |
|
1007 return; |
|
1008 } |
|
1009 mozilla_sampler_stop(); |
|
1010 } |
|
1011 |
|
1012 } |