Bug 674725 - Part O - Receiving SMS: Android backend. r=cjones
authorMounir Lamouri <mounir.lamouri@gmail.com>
Thu, 24 Nov 2011 14:10:20 +0100
changeset 82419 dfb4684b40e09998137cae68c7108c75379a1211
parent 82418 d09ef2ac2a3a17aa2f28e0f72b3225279e4a76cd
child 82420 2729a78cd35e2f1644a8fe1ccd6122c7decb7cd3
child 82422 39d6a73360700b1c76fd4ddb46b5929b73dbfdc4
child 82982 60f879bef90ef16c268b0230cf14ea20ae31c234
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs674725
milestone11.0a1
first release with
nightly win64
dfb4684b40e0 / 11.0a1 / 20111125031016 / files
nightly linux32
nightly linux64
nightly mac
nightly win32
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly win64
Bug 674725 - Part O - Receiving SMS: Android backend. r=cjones
dom/sms/src/Makefile.in
embedding/android/AndroidManifest.xml.in
embedding/android/GeckoApp.java
embedding/android/GeckoAppShell.java
embedding/android/GeckoSmsManager.java
other-licenses/android/APKOpen.cpp
widget/src/android/AndroidJNI.cpp
--- a/dom/sms/src/Makefile.in
+++ b/dom/sms/src/Makefile.in
@@ -59,16 +59,17 @@ include $(topsrcdir)/dom/dom-config.mk
 EXPORTS_NAMESPACES = mozilla/dom/sms
 
 EXPORTS_mozilla/dom/sms = \
   SmsChild.h \
   SmsParent.h \
   SmsServiceFactory.h \
   Constants.h \
   Types.h \
+  SmsMessage.h \
   $(NULL)
 
 CPPSRCS = \
   SmsManager.cpp \
   SmsService.cpp \
   SmsIPCService.cpp \
   SmsServiceFactory.cpp \
   SmsParent.cpp \
--- a/embedding/android/AndroidManifest.xml.in
+++ b/embedding/android/AndroidManifest.xml.in
@@ -18,16 +18,17 @@
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
 
     <uses-permission android:name="android.permission.WAKE_LOCK"/>
     <uses-permission android:name="android.permission.VIBRATE"/>
 
     <!-- WebSMS -->
     <uses-permission android:name="android.permission.SEND_SMS"/>
+    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
 
     <uses-feature android:name="android.hardware.location" android:required="false"/>
     <uses-feature android:name="android.hardware.location.gps" android:required="false"/>
     <uses-feature android:name="android.hardware.touchscreen"/>
 
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-feature android:name="android.hardware.camera" android:required="false"/>
     <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
--- a/embedding/android/GeckoApp.java
+++ b/embedding/android/GeckoApp.java
@@ -83,16 +83,17 @@ abstract public class GeckoApp
     public static GeckoApp mAppContext;
     public static boolean mFullscreen = false;
     public static File sGREDir = null;
     static Thread mLibLoadThread = null;
     public Handler mMainHandler;
     private IntentFilter mConnectivityFilter;
     private BroadcastReceiver mConnectivityReceiver;
     private BroadcastReceiver mBatteryReceiver;
+    private BroadcastReceiver mSmsReceiver;
 
     enum LaunchState {PreLaunch, Launching, WaitForDebugger,
                       Launched, GeckoRunning, GeckoExiting};
     private static LaunchState sLaunchState = LaunchState.PreLaunch;
     private static boolean sTryCatchAttached = false;
 
 
     static boolean checkLaunchState(LaunchState checkState) {
@@ -408,16 +409,21 @@ abstract public class GeckoApp
         mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         mConnectivityReceiver = new GeckoConnectivityReceiver();
 
         IntentFilter batteryFilter = new IntentFilter();
         batteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
         mBatteryReceiver = new GeckoBatteryManager();
         registerReceiver(mBatteryReceiver, batteryFilter);
 
+        IntentFilter smsFilter = new IntentFilter();
+        smsFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
+        mSmsReceiver = new GeckoSmsManager();
+        registerReceiver(mSmsReceiver, smsFilter);
+
         if (!checkAndSetLaunchState(LaunchState.PreLaunch,
                                     LaunchState.Launching))
             return;
 
         checkAndLaunchUpdate();
         mLibLoadThread = new Thread(new Runnable() {
             public void run() {
                 // At some point while loading the gecko libs our default locale gets set
@@ -560,23 +566,25 @@ abstract public class GeckoApp
         GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_START));
         super.onStart();
     }
 
     @Override
     public void onDestroy()
     {
         Log.i(LOG_FILE_NAME, "destroy");
+
         // Tell Gecko to shutting down; we'll end up calling System.exit()
         // in onXreExit.
         if (isFinishing())
             GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_SHUTDOWN));
 
         super.onDestroy();
 
+        unregisterReceiver(mSmsReceiver);
         unregisterReceiver(mBatteryReceiver);
     }
 
     @Override
     public void onConfigurationChanged(android.content.res.Configuration newConfig)
     {
         Log.i(LOG_FILE_NAME, "configuration changed");
         // nothing, just ignore
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -113,16 +113,18 @@ public class GeckoAppShell
     public static native void loadLibs(String apkName, boolean shouldExtract);
     public static native void onChangeNetworkLinkStatus(String status);
     public static native void reportJavaCrash(String stack);
 
     public static native void processNextNativeEvent();
 
     public static native void notifyBatteryChange(double aLevel, boolean aCharging, double aRemainingTime);
 
+    public static native void notifySmsReceived(String aSender, String aBody, long aTimestamp);
+
     // A looper thread, accessed by GeckoAppShell.getHandler
     private static class LooperThread extends Thread {
         public SynchronousQueue<Handler> mHandlerQueue =
             new SynchronousQueue<Handler>();
         
         public void run() {
             Looper.prepare();
             try {
--- a/embedding/android/GeckoSmsManager.java
+++ b/embedding/android/GeckoSmsManager.java
@@ -36,22 +36,57 @@
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko;
 
 import java.util.ArrayList;
 
 import android.util.Log;
 
+import android.content.Intent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+
+import android.os.Bundle;
+
 import android.telephony.SmsManager;
+import android.telephony.SmsMessage;
 
 public class GeckoSmsManager
+  extends BroadcastReceiver
 {
   final static int kMaxMessageSize = 160;
 
+  @Override
+  public void onReceive(Context context, Intent intent) {
+    if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
+      // TODO: Try to find the receiver number to be able to populate
+      //       SmsMessage.receiver.
+      // TODO: Get the id and the date from the stock app saved message.
+      //       Using the stock app saved message require us to wait for it to
+      //       be saved which can lead to race conditions.
+
+      Bundle bundle = intent.getExtras();
+
+      if (bundle == null) {
+        return;
+      }
+
+      Object[] pdus = (Object[]) bundle.get("pdus");
+
+      for (int i=0; i<pdus.length; ++i) {
+        SmsMessage msg = SmsMessage.createFromPdu((byte[])pdus[i]);
+
+        GeckoAppShell.notifySmsReceived(msg.getDisplayOriginatingAddress(),
+                                        msg.getDisplayMessageBody(),
+                                        System.currentTimeMillis());
+      }
+    }
+  }
+
   public static int getNumberOfMessagesForText(String aText) {
     return SmsManager.getDefault().divideMessage(aText).size();
   }
 
   public static void send(String aNumber, String aMessage) {
     /*
      * TODO:
      * This is a basic send method that doesn't handle errors, doesn't listen to
--- a/other-licenses/android/APKOpen.cpp
+++ b/other-licenses/android/APKOpen.cpp
@@ -294,16 +294,17 @@ SHELL_WRAPPER3(callObserver, jstring, js
 SHELL_WRAPPER1(removeObserver, jstring)
 SHELL_WRAPPER1(onChangeNetworkLinkStatus, jstring)
 SHELL_WRAPPER1(reportJavaCrash, jstring)
 SHELL_WRAPPER0(executeNextRunnable)
 SHELL_WRAPPER1(cameraCallbackBridge, jbyteArray)
 SHELL_WRAPPER1(notifyUriVisited, jstring)
 SHELL_WRAPPER3(notifyBatteryChange, jdouble, jboolean, jdouble);
 SHELL_WRAPPER1_WITH_RETURN(canCreateFixupURI, bool, jstring);
+SHELL_WRAPPER3(notifySmsReceived, jstring, jstring, jlong);
 
 static void * xul_handle = NULL;
 static time_t apk_mtime = 0;
 #ifdef DEBUG
 extern "C" int extractLibs = 1;
 #else
 extern "C" int extractLibs = 0;
 #endif
@@ -699,16 +700,17 @@ loadLibs(const char *apkName)
   GETFUNC(removeObserver);
   GETFUNC(onChangeNetworkLinkStatus);
   GETFUNC(reportJavaCrash);
   GETFUNC(executeNextRunnable);
   GETFUNC(cameraCallbackBridge);
   GETFUNC(notifyUriVisited);
   GETFUNC(notifyBatteryChange);
   GETFUNC(canCreateFixupURI);
+  GETFUNC(notifySmsReceived);
 #undef GETFUNC
   sStartupTimeline = (uint64_t *)__wrap_dlsym(xul_handle, "_ZN7mozilla15StartupTimeline16sStartupTimelineE");
   gettimeofday(&t1, 0);
   struct rusage usage2;
   getrusage(RUSAGE_THREAD, &usage2);
   __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loaded libs in %dms total, %dms user, %dms system, %d faults",
                       (t1.tv_sec - t0.tv_sec)*1000 + (t1.tv_usec - t0.tv_usec)/1000, 
                       (usage2.ru_utime.tv_sec - usage1.ru_utime.tv_sec)*1000 + (usage2.ru_utime.tv_usec - usage1.ru_utime.tv_usec)/1000,
--- a/widget/src/android/AndroidJNI.cpp
+++ b/widget/src/android/AndroidJNI.cpp
@@ -57,18 +57,23 @@
 #include "nsAndroidHistory.h"
 #endif
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsICrashReporter.h"
 #include "nsExceptionHandler.h"
 #endif
 
+#include "mozilla/dom/sms/SmsMessage.h"
+#include "mozilla/dom/sms/Constants.h"
+#include "mozilla/dom/sms/Types.h"
+#include "mozilla/dom/sms/PSms.h"
 
 using namespace mozilla;
+using namespace mozilla::dom::sms;
 
 /* Forward declare all the JNI methods as extern "C" */
 
 extern "C" {
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv *, jclass);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoOfEvent(JNIEnv *, jclass, jobject event);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_processNextNativeEvent(JNIEnv *, jclass);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_setSoftwareLayerClient(JNIEnv *jenv, jclass, jobject sv);
@@ -78,16 +83,17 @@ extern "C" {
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_callObserver(JNIEnv *, jclass, jstring observerKey, jstring topic, jstring data);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_removeObserver(JNIEnv *jenv, jclass, jstring jObserverKey);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus(JNIEnv *, jclass, jstring status);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv *, jclass, jstring stack);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_executeNextRunnable(JNIEnv *, jclass);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyUriVisited(JNIEnv *, jclass, jstring uri);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv* jenv, jclass, jdouble, jboolean, jdouble);
     NS_EXPORT bool JNICALL Java_org_mozilla_gecko_GeckoAppShell_canCreateFixupURI(JNIEnv* jenv, jclass, jstring text);
+    NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifySmsReceived(JNIEnv* jenv, jclass, jstring, jstring, jlong);
 }
 
 
 /*
  * Incoming JNI methods
  */
 
 NS_EXPORT void JNICALL
@@ -246,8 +252,42 @@ Java_org_mozilla_gecko_GeckoAppShell_can
     __android_log_print(ANDROID_LOG_INFO, "GeckoJNI", "%s", __PRETTY_FUNCTION__);
 
     const jchar *textChars = jenv->GetStringChars(text, NULL);
     NS_ConvertUTF16toUTF8 uriString(textChars);
     jenv->ReleaseStringChars(text, textChars);
 
     return AndroidBridge::Bridge()->CanCreateFixupURI(uriString);
 }
+
+NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_notifySmsReceived(JNIEnv* jenv, jclass,
+                                                       jstring aSender,
+                                                       jstring aBody,
+                                                       jlong aTimestamp)
+{
+    class NotifySmsReceivedRunnable : public nsRunnable {
+    public:
+      NotifySmsReceivedRunnable(const SmsMessageData& aMessageData)\
+        : mMessageData(aMessageData)
+      {}
+
+      NS_IMETHODIMP Run() {
+        nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+        if (!obs) {
+          return NS_OK;
+        }
+
+        nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData);
+        obs->NotifyObservers(message, kSmsReceivedObserverTopic, nsnull);
+        return NS_OK;
+      }
+
+    private:
+      SmsMessageData mMessageData;
+    };
+
+    SmsMessageData message(0, eDeliveryState_Received, nsJNIString(aSender, jenv), EmptyString(),
+                           nsJNIString(aBody, jenv), aTimestamp);
+
+    nsCOMPtr<nsIRunnable> runnable = new NotifySmsReceivedRunnable(message);
+    NS_DispatchToMainThread(runnable);
+}