summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKoushik Dutta <koushd@gmail.com>2013-06-19 09:12:01 -0700
committerKoushik Dutta <koushd@gmail.com>2013-06-29 21:29:22 -0700
commit3dba6580fc385399d726233692d5abb3b5b8208b (patch)
tree8a5bbd93c47d6dee881d02b86e8547a165c29775
parent769f93cddca0b70ab9cb8895bb08645c9db8ccd7 (diff)
downloadframeworks_opt_telephony-3dba6580fc385399d726233692d5abb3b5b8208b.zip
frameworks_opt_telephony-3dba6580fc385399d726233692d5abb3b5b8208b.tar.gz
frameworks_opt_telephony-3dba6580fc385399d726233692d5abb3b5b8208b.tar.bz2
Add SMS Middleware layer.
Change-Id: I4fff0c584f8fce9c5f2f4fe86a82fe6480c307c7
-rw-r--r--Android.mk1
-rw-r--r--src/java/android/telephony/SmsMessage.java11
-rw-r--r--src/java/com/android/internal/telephony/ISms.aidl6
-rw-r--r--src/java/com/android/internal/telephony/ISmsMiddleware.aidl12
-rw-r--r--src/java/com/android/internal/telephony/IccSmsInterfaceManager.java9
-rw-r--r--src/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java86
-rw-r--r--src/java/com/android/internal/telephony/PhoneProxy.java1
-rw-r--r--src/java/com/android/internal/telephony/SyntheticSmsMessage.java109
8 files changed, 231 insertions, 4 deletions
diff --git a/Android.mk b/Android.mk
index 9e07849..fa7bbeb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -19,6 +19,7 @@ include $(CLEAR_VARS)
LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/src/java
LOCAL_SRC_FILES := \
src/java/com/android/internal/telephony/ISms.aidl \
+ src/java/com/android/internal/telephony/ISmsMiddleware.aidl \
src/java/com/android/internal/telephony/IIccPhoneBook.aidl \
src/java/com/android/internal/telephony/EventLogTags.logtags \
diff --git a/src/java/android/telephony/SmsMessage.java b/src/java/android/telephony/SmsMessage.java
index b94609e..eaaf4b0 100644
--- a/src/java/android/telephony/SmsMessage.java
+++ b/src/java/android/telephony/SmsMessage.java
@@ -90,6 +90,12 @@ public class SmsMessage {
*/
public static final String FORMAT_3GPP2 = "3gpp2";
+ /**
+ * Indicates a synthetic SMS message.
+ * @hide
+ */
+ public static final String FORMAT_SYNTHETIC = "synthetic";
+
/** Contains actual SmsMessage. Only public for debugging and for framework layer.
*
* @hide
@@ -137,6 +143,9 @@ public class SmsMessage {
int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
String format = (PHONE_TYPE_CDMA == activePhone) ?
SmsConstants.FORMAT_3GPP2 : SmsConstants.FORMAT_3GPP;
+ if (com.android.internal.telephony.SyntheticSmsMessage.isSyntheticPdu(pdu)) {
+ format = FORMAT_SYNTHETIC;
+ }
return createFromPdu(pdu, format);
}
@@ -157,6 +166,8 @@ public class SmsMessage {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
} else if (SmsConstants.FORMAT_3GPP.equals(format)) {
wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromPdu(pdu);
+ } else if (FORMAT_SYNTHETIC.equals(format)) {
+ wrappedMessage = com.android.internal.telephony.SyntheticSmsMessage.createFromPdu(pdu);
} else {
Log.e(LOG_TAG, "createFromPdu(): unsupported message format " + format);
return null;
diff --git a/src/java/com/android/internal/telephony/ISms.aidl b/src/java/com/android/internal/telephony/ISms.aidl
index 1fd9f70..0f50ff0 100644
--- a/src/java/com/android/internal/telephony/ISms.aidl
+++ b/src/java/com/android/internal/telephony/ISms.aidl
@@ -18,6 +18,9 @@ package com.android.internal.telephony;
import android.app.PendingIntent;
import com.android.internal.telephony.SmsRawData;
+import com.android.internal.telephony.ISmsMiddleware;
+
+import java.util.List;
/** Interface for applications to access the ICC phone book.
*
@@ -34,6 +37,9 @@ import com.android.internal.telephony.SmsRawData;
*/
interface ISms {
+ void registerSmsMiddleware(String name, ISmsMiddleware middleware);
+ void synthesizeMessages(String originatingAddress, String scAddress, in List<String> messages, long timestampMillis);
+
/**
* Retrieves all messages currently stored on ICC.
*
diff --git a/src/java/com/android/internal/telephony/ISmsMiddleware.aidl b/src/java/com/android/internal/telephony/ISmsMiddleware.aidl
new file mode 100644
index 0000000..1268f2e
--- /dev/null
+++ b/src/java/com/android/internal/telephony/ISmsMiddleware.aidl
@@ -0,0 +1,12 @@
+package com.android.internal.telephony;
+
+import android.app.PendingIntent;
+
+interface ISmsMiddleware {
+ boolean onSendText(in String destAddr, in String scAddr, in String text,
+ in PendingIntent sentIntent, in PendingIntent deliveryIntent);
+
+ boolean onSendMultipartText(in String destinationAddress, in String scAddress,
+ in List<String> parts, in List<PendingIntent> sentIntents,
+ in List<PendingIntent> deliveryIntents);
+} \ No newline at end of file
diff --git a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index 525bcd9..b4d13fd 100644
--- a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -18,6 +18,7 @@ package com.android.internal.telephony;
import android.app.PendingIntent;
import android.content.Context;
+import android.os.RemoteException;
import android.util.Log;
import com.android.internal.util.HexDump;
@@ -48,6 +49,14 @@ public abstract class IccSmsInterfaceManager extends ISms.Stub {
"android.permission.SEND_SMS", message);
}
+ @Override
+ public void registerSmsMiddleware(String name, ISmsMiddleware middleware) throws android.os.RemoteException {
+ }
+
+ @Override
+ public void synthesizeMessages(String originatingAddress, String scAddress, List<String> messages, long timestampMillis) throws RemoteException {
+ }
+
/**
* Send a data based SMS to a specific application port.
*
diff --git a/src/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java b/src/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java
index f80aa67..44882ef 100644
--- a/src/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java
+++ b/src/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java
@@ -16,26 +16,86 @@
package com.android.internal.telephony;
+import java.util.Hashtable;
+import java.util.List;
+
+import android.app.Activity;
import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.PowerManager;
+import android.os.RemoteException;
import android.os.ServiceManager;
-
-import java.util.List;
+import android.os.SystemProperties;
+import android.provider.Telephony.Sms.Intents;
+import android.telephony.SmsMessage;
public class IccSmsInterfaceManagerProxy extends ISms.Stub {
private IccSmsInterfaceManager mIccSmsInterfaceManager;
+ private Hashtable<String, ISmsMiddleware> mMiddleware = new Hashtable<String, ISmsMiddleware>();
- public IccSmsInterfaceManagerProxy(IccSmsInterfaceManager
- iccSmsInterfaceManager) {
+ public IccSmsInterfaceManagerProxy(Context context,
+ IccSmsInterfaceManager iccSmsInterfaceManager) {
+ this.mContext = context;
this.mIccSmsInterfaceManager = iccSmsInterfaceManager;
if(ServiceManager.getService("isms") == null) {
ServiceManager.addService("isms", this);
}
+
+ createWakelock();
}
public void setmIccSmsInterfaceManager(IccSmsInterfaceManager iccSmsInterfaceManager) {
this.mIccSmsInterfaceManager = iccSmsInterfaceManager;
}
+ private void createWakelock() {
+ PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SMSDispatcher");
+ mWakeLock.setReferenceCounted(true);
+ }
+
+ @Override
+ public void registerSmsMiddleware(String name, ISmsMiddleware middleware) throws android.os.RemoteException {
+ if (!"1".equals(SystemProperties.get("persist.sys.sms_debug", "0"))) {
+ mContext.enforceCallingPermission(
+ "android.permission.INTERCEPT_SMS", "");
+ }
+ mMiddleware.put(name, middleware);
+ }
+
+ private Context mContext;
+ private PowerManager.WakeLock mWakeLock;
+ private static final int WAKE_LOCK_TIMEOUT = 5000;
+ private void dispatchPdus(byte[][] pdus) {
+ Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION);
+ intent.putExtra("pdus", pdus);
+ intent.putExtra("format", SmsMessage.FORMAT_SYNTHETIC);
+ dispatch(intent, SMSDispatcher.RECEIVE_SMS_PERMISSION);
+ }
+
+ private void dispatch(Intent intent, String permission) {
+ // Hold a wake lock for WAKE_LOCK_TIMEOUT seconds, enough to give any
+ // receivers time to take their own wake locks.
+ mWakeLock.acquire(WAKE_LOCK_TIMEOUT);
+ mContext.sendOrderedBroadcast(intent, permission);
+ }
+
+ @Override
+ public void synthesizeMessages(String originatingAddress, String scAddress, List<String> messages, long timestampMillis) throws RemoteException {
+ // if not running in debug mode
+ if (!"1".equals(SystemProperties.get("persist.sys.sms_debug", "0"))) {
+ mContext.enforceCallingPermission(
+ "android.permission.BROADCAST_SMS", "");
+ }
+ byte[][] pdus = new byte[messages.size()][];
+ for (int i = 0; i < messages.size(); i++) {
+ SyntheticSmsMessage message = new SyntheticSmsMessage(originatingAddress, scAddress, messages.get(i), timestampMillis);
+ pdus[i] = message.getPdu();
+ }
+ dispatchPdus(pdus);
+ }
+
public boolean
updateMessageOnIccEf(int index, int status, byte[] pdu) throws android.os.RemoteException {
return mIccSmsInterfaceManager.updateMessageOnIccEf(index, status, pdu);
@@ -58,12 +118,30 @@ public class IccSmsInterfaceManagerProxy extends ISms.Stub {
public void sendText(String destAddr, String scAddr,
String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+ for (ISmsMiddleware middleware: mMiddleware.values()) {
+ try {
+ if (middleware.onSendText(destAddr, scAddr, text, sentIntent, deliveryIntent))
+ return;
+ }
+ catch (Exception e) {
+ // TOOD: remove the busted middleware?
+ }
+ }
mIccSmsInterfaceManager.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent);
}
public void sendMultipartText(String destAddr, String scAddr,
List<String> parts, List<PendingIntent> sentIntents,
List<PendingIntent> deliveryIntents) throws android.os.RemoteException {
+ for (ISmsMiddleware middleware: mMiddleware.values()) {
+ try {
+ if (middleware.onSendMultipartText(destAddr, scAddr, parts, sentIntents, deliveryIntents))
+ return;
+ }
+ catch (Exception e) {
+ // TOOD: remove the busted middleware?
+ }
+ }
mIccSmsInterfaceManager.sendMultipartText(destAddr, scAddr,
parts, sentIntents, deliveryIntents);
}
diff --git a/src/java/com/android/internal/telephony/PhoneProxy.java b/src/java/com/android/internal/telephony/PhoneProxy.java
index 7cef426..38fe68d 100644
--- a/src/java/com/android/internal/telephony/PhoneProxy.java
+++ b/src/java/com/android/internal/telephony/PhoneProxy.java
@@ -71,6 +71,7 @@ public class PhoneProxy extends Handler implements Phone {
mResetModemOnRadioTechnologyChange = SystemProperties.getBoolean(
TelephonyProperties.PROPERTY_RESET_ON_RADIO_TECH_CHANGE, false);
mIccSmsInterfaceManagerProxy = new IccSmsInterfaceManagerProxy(
+ phone.getContext(),
phone.getIccSmsInterfaceManager());
mIccPhoneBookInterfaceManagerProxy = new IccPhoneBookInterfaceManagerProxy(
phone.getIccPhoneBookInterfaceManager());
diff --git a/src/java/com/android/internal/telephony/SyntheticSmsMessage.java b/src/java/com/android/internal/telephony/SyntheticSmsMessage.java
new file mode 100644
index 0000000..14bfca8
--- /dev/null
+++ b/src/java/com/android/internal/telephony/SyntheticSmsMessage.java
@@ -0,0 +1,109 @@
+package com.android.internal.telephony;
+
+import org.json.JSONObject;
+
+import com.android.internal.telephony.SmsConstants.MessageClass;
+
+public class SyntheticSmsMessage extends SmsMessageBase {
+ public static class SyntheticAddress extends SmsAddress {
+ }
+
+ public static boolean isSyntheticPdu(byte[] pdu) {
+ try {
+ JSONObject json = new JSONObject(new String(pdu));
+ return json.optBoolean("synthetic", false);
+ }
+ catch (Exception e) {
+ }
+ return false;
+ }
+
+ public static SyntheticSmsMessage createFromPdu(byte[] pdu) {
+ try {
+ // TODO: use Parcelable or Bundle or something that serializes?
+ JSONObject json = new JSONObject(new String(pdu));
+ SyntheticSmsMessage message = new SyntheticSmsMessage(
+ json.getString("originatingAddress"),
+ json.optString("scAddress", null),
+ json.getString("messageBody"),
+ json.getLong("timestampMillis"));
+ return message;
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public SyntheticSmsMessage(String originatingAddress, String scAddress, String messageBody, long timestampMillis) {
+ this.originatingAddress = new SyntheticAddress();
+ this.originatingAddress.address = originatingAddress;
+
+ this.messageBody = messageBody;
+ this.scTimeMillis = timestampMillis;
+ this.scAddress = scAddress;
+
+ try {
+ JSONObject json = new JSONObject();
+ json.put("originatingAddress", originatingAddress);
+ json.put("scAddress", scAddress);
+ json.put("messageBody", messageBody);
+ json.put("timestampMillis", timestampMillis);
+ json.put("synthetic", true);
+ this.mPdu = json.toString().getBytes();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public MessageClass getMessageClass() {
+ return SmsConstants.MessageClass.UNKNOWN;
+ }
+
+ @Override
+ public int getProtocolIdentifier() {
+ return 0;
+ }
+
+ @Override
+ public boolean isReplace() {
+ return false;
+ }
+
+ @Override
+ public boolean isCphsMwiMessage() {
+ return false;
+ }
+
+ @Override
+ public boolean isMWIClearMessage() {
+ return false;
+ }
+
+ @Override
+ public boolean isMWISetMessage() {
+ return false;
+ }
+
+ @Override
+ public boolean isMwiDontStore() {
+ return false;
+ }
+
+ @Override
+ public int getStatus() {
+ return 0;
+ }
+
+ @Override
+ public boolean isStatusReportMessage() {
+ return false;
+ }
+
+ @Override
+ public boolean isReplyPathPresent() {
+ return false;
+ }
+}