Upstream version 11.39.244.0
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / android / core_internal / src / org / xwalk / core / internal / extension / api / messaging / MessagingSmsManager.java
1 // Copyright (c) 2013 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.xwalk.core.internal.extension.api.messaging;
6
7 import android.app.Activity;
8 import android.app.PendingIntent;
9 import android.content.BroadcastReceiver;
10 import android.content.ContentResolver;  
11 import android.content.ContentValues;
12 import android.content.Context;
13 import android.content.Intent;
14 import android.content.IntentFilter;
15 import android.os.Bundle;
16 import android.telephony.SmsManager;
17 import android.telephony.SmsMessage;
18 import android.telephony.TelephonyManager;
19 import android.net.Uri; 
20 import android.util.Log; 
21
22 import java.lang.ref.WeakReference;
23 import java.text.SimpleDateFormat;
24 import java.util.ArrayList;
25 import java.util.UUID;
26
27 import org.json.JSONArray;
28 import org.json.JSONException;
29 import org.json.JSONObject;
30 import org.xwalk.core.internal.extension.api.messaging.Messaging;
31
32 public class MessagingSmsManager {
33     private final static String TAG = "MessagingSmsManager";
34     private final static String EXTRA_MSGID = "asyncCallId";
35     private final static String EXTRA_MSGTEXT = "message";
36     private final static String EXTRA_MSGTO = "to";
37     private final static String EXTRA_MSGINSTANCEID = "instanceid";
38     private final static String EXTRA_UUID= "UUID";
39     private final static String DEFAULT_SERVICE_ID = "sim0";
40     private final WeakReference<Activity> mActivity;
41     private final Messaging mMessagingHandler;
42     private BroadcastReceiver mSmsSentReceiver, mSmsDeliveredReceiver,
43                               mSmsReceiveReceiver, mSmsServiceReceiver;
44     private String mUUID;
45
46     private abstract class MessagingReceiver extends BroadcastReceiver {
47         protected Messaging mMessaging;
48
49         public MessagingReceiver(Messaging messaging) {
50             mMessaging = messaging;
51         }
52     }
53
54     MessagingSmsManager(Activity activity, Messaging messaging) {
55         mActivity = new WeakReference<Activity>(activity);
56         mMessagingHandler = messaging;
57         mUUID = UUID.randomUUID().toString();
58     }
59
60     private boolean checkService(String serviceID) {
61         Activity activity = mActivity.get();
62         if (activity == null) return false;
63         TelephonyManager tm = 
64             (TelephonyManager) activity.getSystemService(Context.TELEPHONY_SERVICE);
65         return (TelephonyManager.SIM_STATE_READY == tm.getSimState());
66     }
67
68     public void onSmsSend(int instanceID, JSONObject jsonMsg) {
69         if (!checkService(DEFAULT_SERVICE_ID)) {
70             Log.e(TAG, "No Sim Card");
71         }
72         Activity activity = mActivity.get();
73         if (activity == null) return;
74
75         String asyncCallId = null;
76         JSONObject eventBody = null;
77         String phone = null;
78         String smsMessage = null;
79         try {
80             asyncCallId = jsonMsg.getString("asyncCallId");
81             eventBody = jsonMsg.getJSONObject("data");
82             phone = eventBody.getString("phone");
83             smsMessage = eventBody.getString("message");
84         } catch (JSONException e) {
85             e.printStackTrace();
86             return;
87         }
88         
89         SmsManager sms = SmsManager.getDefault();
90         Intent intentSmsSent = new Intent("SMS_SENT");
91         intentSmsSent.putExtra(EXTRA_MSGID, asyncCallId);
92         intentSmsSent.putExtra(EXTRA_MSGTEXT, smsMessage);
93         intentSmsSent.putExtra(EXTRA_MSGTO, phone);
94         String instanceIDString = Integer.toString(instanceID);
95         intentSmsSent.putExtra(EXTRA_MSGINSTANCEID, instanceIDString);
96         intentSmsSent.putExtra(EXTRA_UUID, mUUID);
97         int promiseIdInt = Integer.valueOf(asyncCallId);
98         PendingIntent piSent = PendingIntent.getBroadcast(activity, 
99                                                           promiseIdInt, 
100                                                           intentSmsSent, 
101                                                           PendingIntent.FLAG_ONE_SHOT);
102         Intent intentSmsDelivered = new Intent("SMS_DELIVERED");
103         intentSmsDelivered.putExtra(EXTRA_MSGID, asyncCallId);
104         intentSmsDelivered.putExtra(EXTRA_MSGTEXT, smsMessage);
105         intentSmsDelivered.putExtra(EXTRA_MSGINSTANCEID, instanceIDString);
106         intentSmsDelivered.putExtra(EXTRA_UUID, mUUID);
107         PendingIntent piDelivered = PendingIntent.getBroadcast(activity, 
108                                                                -promiseIdInt, 
109                                                                intentSmsDelivered,
110                                                                PendingIntent.FLAG_ONE_SHOT);
111         try {
112             sms.sendTextMessage(phone, null, smsMessage, piSent, piDelivered);
113         } catch (Exception e) {
114             Log.e(TAG, "Failed to send SMS message.", e);
115         }
116     }
117
118     public void onSmsClear(int instanceID, JSONObject jsonMsg) {
119         Activity activity = mActivity.get();
120         if (activity == null) return;
121
122         String asyncCallId = null, cmd = null;
123         JSONObject eventBody = null;
124         String serviceID = null;
125         try {
126             asyncCallId = jsonMsg.getString("asyncCallId");
127             cmd = jsonMsg.getString("cmd");
128             eventBody = jsonMsg.getJSONObject("data");
129             serviceID = eventBody.getString("serviceID");
130         } catch (JSONException e) {
131             e.printStackTrace();
132             return;
133         }
134
135         ContentResolver cr = activity.getContentResolver();
136         cr.delete(Uri.parse("content://sms"), null, null);
137
138         JSONObject jsonMsgRet = null;
139         try {
140             jsonMsgRet = new JSONObject();
141             jsonMsgRet.put("asyncCallId", asyncCallId);
142             jsonMsgRet.put("cmd", cmd + "_ret");
143             JSONObject jsData = new JSONObject();
144             jsonMsgRet.put("data", jsData);
145             jsData.put("error", false);
146             JSONObject jsBody = new JSONObject();
147             jsData.put("body", jsBody);
148             jsBody.put("value", serviceID);
149         } catch (JSONException e) {
150             e.printStackTrace();
151             return;
152         }
153
154         mMessagingHandler.postMessage(instanceID, jsonMsgRet.toString());
155     }
156
157     public void onSmsSegmentInfo(int instanceID, JSONObject jsonMsg) {
158         String asyncCallId = null;
159         JSONObject eventBody = null;
160         String text = null;
161         try {
162             asyncCallId = jsonMsg.getString("asyncCallId");
163             eventBody = jsonMsg.getJSONObject("data");
164             text = eventBody.getString("text");
165
166             if (null == text) {
167                 Log.e(TAG, "No \"text\" attribute.");
168                 return;
169             }
170         } catch (JSONException e) {
171             e.printStackTrace();
172             return;
173         }
174         
175         SmsManager sms = SmsManager.getDefault();
176         ArrayList<String> segs = sms.divideMessage(text);
177         try {
178             JSONObject jsonMsgRet = new JSONObject();
179             jsonMsgRet.put("cmd", "msg_smsSegmentInfo_ret");
180             jsonMsgRet.put("asyncCallId", asyncCallId);
181             JSONObject jsData = new JSONObject();
182             jsonMsgRet.put("data", jsData);
183             jsData.put("error", false);
184             JSONObject jsBody = new JSONObject();
185             jsData.put("body", jsBody);
186             jsBody.put("segments", segs.size());
187             jsBody.put("charsPerSegment", segs.get(0).length());
188             jsBody.put("charsAvailableInLastSegment", segs.get(segs.size() - 1).length());
189             
190             mMessagingHandler.postMessage(instanceID, jsonMsgRet.toString());
191          } catch (JSONException e) {
192             e.printStackTrace();
193             return;
194         }        
195     }
196
197     public void registerIntentFilters() {
198         Activity activity = mActivity.get();
199         if (activity == null) return;
200
201         mSmsReceiveReceiver = new MessagingReceiver(mMessagingHandler) {
202             @Override
203             public void onReceive(Context context, Intent intent) {
204                 Bundle bundle = intent.getExtras();        
205                 
206                 if(null == bundle) {
207                     return;
208                 }
209
210                 Object[] pdus = (Object[]) bundle.get("pdus");
211                 for (int i=0; i < pdus.length; ++i) {
212                     try {
213                         JSONObject jsonMsg = new JSONObject();
214                         jsonMsg.put("cmd", "received");
215
216                         SmsMessage msgs = SmsMessage.createFromPdu((byte[])pdus[i]);
217                         
218                         JSONObject jsData = new JSONObject();
219                         jsonMsg.put("data", jsData);
220                         JSONObject jsMsg = new JSONObject();
221                         jsData.put("message", jsMsg);
222                         jsMsg.put("messageID", "");
223                         jsMsg.put("type", "sms");
224                         jsMsg.put("serviceID", DEFAULT_SERVICE_ID);
225                         jsMsg.put("from", msgs.getOriginatingAddress());
226                         SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
227                         jsMsg.put("timestamp", sDateFormat.format(new java.util.Date()));
228                         jsMsg.put("body", msgs.getMessageBody().toString());
229                         
230                         mMessaging.broadcastMessage(jsonMsg.toString());
231                      } catch (JSONException e) {
232                         e.printStackTrace();
233                         return;
234                     }
235                 } 
236             }
237         };
238
239         mSmsSentReceiver = new MessagingReceiver(mMessagingHandler) {
240             @Override
241             public void onReceive(Context content, Intent intent) {
242                 Activity activity = mActivity.get();
243                 if (activity == null) return;
244                 String uuid = intent.getStringExtra(EXTRA_UUID);
245                 if (null == uuid || !uuid.equals(mUUID)) return;
246
247                 boolean error = getResultCode() != Activity.RESULT_OK;
248                 String asyncCallId = intent.getStringExtra(EXTRA_MSGID);
249                 String smsMessage = intent.getStringExtra(EXTRA_MSGTEXT);
250                 String to = intent.getStringExtra(EXTRA_MSGTO);
251                 int instanceID = Integer.valueOf(intent.getStringExtra(EXTRA_MSGINSTANCEID));
252
253                 try {
254                     JSONObject jsSentMsg = new JSONObject();
255                     jsSentMsg.put("type", "sms");
256                     jsSentMsg.put("from", "");
257                     jsSentMsg.put("read", true);
258                     jsSentMsg.put("to", to);
259                     jsSentMsg.put("body", smsMessage);
260                     jsSentMsg.put("messageClass", "class1");
261                     jsSentMsg.put("state", error ? "failed" : "sending");
262                     jsSentMsg.put("deliveryStatus", error ? "error" : "pending");
263
264                     JSONObject jsonMsgPromise = new JSONObject();
265                     jsonMsgPromise.put("asyncCallId", asyncCallId);
266                     jsonMsgPromise.put("cmd", "msg_smsSend_ret");
267                     JSONObject jsData = new JSONObject();
268                     jsonMsgPromise.put("data", jsData);
269                     jsData.put("error", error);
270                     jsData.put("body", jsSentMsg);
271
272                     mMessaging.postMessage(instanceID, jsonMsgPromise.toString());
273
274                     JSONObject jsonMsgEvent = new JSONObject();
275                     jsonMsgEvent.put("cmd", "sent");
276                     jsonMsgEvent.put("data", jsSentMsg);
277
278                     mMessaging.broadcastMessage(jsonMsgEvent.toString());
279                 } catch (JSONException e) {
280                     e.printStackTrace();
281                     return;
282                 }
283
284                 ContentValues values = new ContentValues();
285                 values.put("address", to);
286                 values.put("body", smsMessage);
287                 activity.getContentResolver().insert(Uri.parse("content://sms/sent"), values);
288             }
289         };
290
291         mSmsDeliveredReceiver = new MessagingReceiver(mMessagingHandler) {
292             @Override
293             public void onReceive(Context content, Intent intent) {
294                 String uuid = intent.getStringExtra(EXTRA_UUID);
295                 if (null == uuid || !uuid.equals(mUUID)) return;
296
297                 boolean error = getResultCode() != Activity.RESULT_OK;
298                 String asyncCallId = intent.getStringExtra(EXTRA_MSGID);
299                 int instanceID = Integer.valueOf(intent.getStringExtra(EXTRA_MSGINSTANCEID));
300
301                 try {
302                     JSONObject jsonMsg = new JSONObject();
303                     jsonMsg.put("asyncCallId", asyncCallId);
304                     jsonMsg.put("cmd", error ? "deliveryerror": "deliverysuccess");
305                     JSONObject jsData = new JSONObject();
306                     jsonMsg.put("data", jsData);
307                     JSONObject jsEvent = new JSONObject();
308                     jsData.put("event", jsEvent);
309                     jsEvent.put("serviceID", DEFAULT_SERVICE_ID);
310                     jsEvent.put("messageID", "");
311                     jsEvent.put("recipients", "");
312                     SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
313                     jsEvent.put("deliveryTimestamps", sDateFormat.format(new java.util.Date()));
314                     jsData.put("error", error);
315                     mMessaging.postMessage(instanceID, jsonMsg.toString());
316                 } catch (JSONException e) {
317                     e.printStackTrace();
318                     return;
319                 }
320             }
321         };
322
323         mSmsServiceReceiver = new MessagingReceiver(mMessagingHandler) {
324             @Override
325             public void onReceive(Context content, Intent intent) {
326                 try {
327                     JSONObject jsonMsg = new JSONObject();
328                     jsonMsg.put("cmd", 
329                         checkService(DEFAULT_SERVICE_ID) ? "serviceadded": "serviceremoved");
330                     JSONObject jsData = new JSONObject();
331                     jsonMsg.put("data", jsData);
332                     JSONObject jsEvent = new JSONObject();
333                     jsData.put("event", jsEvent);
334                     jsEvent.put("serviceID", DEFAULT_SERVICE_ID);
335                     mMessaging.broadcastMessage(jsonMsg.toString());
336                 } catch (JSONException e) {
337                     e.printStackTrace();
338                     return;
339                 }
340             }
341         };
342
343         activity.registerReceiver(
344             mSmsReceiveReceiver, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
345         activity.registerReceiver(
346             mSmsSentReceiver, new IntentFilter("SMS_SENT"));
347         activity.registerReceiver(
348             mSmsDeliveredReceiver,new IntentFilter("SMS_DELIVERED"));
349         activity.registerReceiver(
350             mSmsServiceReceiver,new IntentFilter("android.intent.action.SIM_STATE_CHANGED"));
351     }
352
353     public void unregisterIntentFilters() {
354         Activity activity = mActivity.get();
355         if (activity == null) return;
356
357         activity.unregisterReceiver(mSmsReceiveReceiver);
358         activity.unregisterReceiver(mSmsSentReceiver);
359         activity.unregisterReceiver(mSmsDeliveredReceiver);
360         activity.unregisterReceiver(mSmsServiceReceiver);
361     }
362
363     public String getServiceIds() {
364         JSONArray serviceIds = new JSONArray();
365
366         // FIXME:(shawn) Android doesn't has the concept of service ID, which means messages are
367         // bundled to given SIM card. And official SDK does not support multiple SIM cards. 
368         // So mock the default one to satisfy the spec.
369         serviceIds.put(DEFAULT_SERVICE_ID);
370         return serviceIds.toString();
371     }
372 }