Loading telephony/java/android/telephony/SmsCbMessage.java 0 → 100644 +267 −0 Original line number Diff line number Diff line /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.telephony; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.gsm.SmsCbHeader; import java.io.UnsupportedEncodingException; /** * Describes an SMS-CB message. * * {@hide} */ public class SmsCbMessage { /** * Cell wide immediate geographical scope */ public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0; /** * PLMN wide geographical scope */ public static final int GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1; /** * Location / service area wide geographical scope */ public static final int GEOGRAPHICAL_SCOPE_LA_WIDE = 2; /** * Cell wide geographical scope */ public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE = 3; /** * Create an instance of this class from a received PDU * * @param pdu PDU bytes * @return An instance of this class, or null if invalid pdu */ public static SmsCbMessage createFromPdu(byte[] pdu) { try { return new SmsCbMessage(pdu); } catch (IllegalArgumentException e) { return null; } } /** * Languages in the 0000xxxx DCS group as defined in 3GPP TS 23.038, section 5. */ private static final String[] LANGUAGE_CODES_GROUP_0 = { "de", "en", "it", "fr", "es", "nl", "sv", "da", "pt", "fi", "no", "el", "tr", "hu", "pl", null }; /** * Languages in the 0010xxxx DCS group as defined in 3GPP TS 23.038, section 5. */ private static final String[] LANGUAGE_CODES_GROUP_2 = { "cs", "he", "ar", "ru", "is", null, null, null, null, null, null, null, null, null, null, null }; private static final char CARRIAGE_RETURN = 0x0d; private SmsCbHeader mHeader; private String mLanguage; private String mBody; private SmsCbMessage(byte[] pdu) throws IllegalArgumentException { mHeader = new SmsCbHeader(pdu); parseBody(pdu); } /** * Return the geographical scope of this message, one of * {@link #GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE}, * {@link #GEOGRAPHICAL_SCOPE_PLMN_WIDE}, * {@link #GEOGRAPHICAL_SCOPE_LA_WIDE}, * {@link #GEOGRAPHICAL_SCOPE_CELL_WIDE} * * @return Geographical scope */ public int getGeographicalScope() { return mHeader.geographicalScope; } /** * Get the ISO-639-1 language code for this message, or null if unspecified * * @return Language code */ public String getLanguageCode() { return mLanguage; } /** * Get the body of this message, or null if no body available * * @return Body, or null */ public String getMessageBody() { return mBody; } /** * Get the message identifier of this message (0-65535) * * @return Message identifier */ public int getMessageIdentifier() { return mHeader.messageIdentifier; } /** * Get the message code of this message (0-1023) * * @return Message code */ public int getMessageCode() { return mHeader.messageCode; } /** * Get the update number of this message (0-15) * * @return Update number */ public int getUpdateNumber() { return mHeader.updateNumber; } private void parseBody(byte[] pdu) { int encoding; boolean hasLanguageIndicator = false; // Extract encoding and language from DCS, as defined in 3gpp TS 23.038, // section 5. switch ((mHeader.dataCodingScheme & 0xf0) >> 4) { case 0x00: encoding = SmsMessage.ENCODING_7BIT; mLanguage = LANGUAGE_CODES_GROUP_0[mHeader.dataCodingScheme & 0x0f]; break; case 0x01: hasLanguageIndicator = true; if ((mHeader.dataCodingScheme & 0x0f) == 0x01) { encoding = SmsMessage.ENCODING_16BIT; } else { encoding = SmsMessage.ENCODING_7BIT; } break; case 0x02: encoding = SmsMessage.ENCODING_7BIT; mLanguage = LANGUAGE_CODES_GROUP_2[mHeader.dataCodingScheme & 0x0f]; break; case 0x03: encoding = SmsMessage.ENCODING_7BIT; break; case 0x04: case 0x05: switch ((mHeader.dataCodingScheme & 0x0c) >> 2) { case 0x01: encoding = SmsMessage.ENCODING_8BIT; break; case 0x02: encoding = SmsMessage.ENCODING_16BIT; break; case 0x00: default: encoding = SmsMessage.ENCODING_7BIT; break; } break; case 0x06: case 0x07: // Compression not supported case 0x09: // UDH structure not supported case 0x0e: // Defined by the WAP forum not supported encoding = SmsMessage.ENCODING_UNKNOWN; break; case 0x0f: if (((mHeader.dataCodingScheme & 0x04) >> 2) == 0x01) { encoding = SmsMessage.ENCODING_8BIT; } else { encoding = SmsMessage.ENCODING_7BIT; } break; default: // Reserved values are to be treated as 7-bit encoding = SmsMessage.ENCODING_7BIT; break; } switch (encoding) { case SmsMessage.ENCODING_7BIT: mBody = GsmAlphabet.gsm7BitPackedToString(pdu, SmsCbHeader.PDU_HEADER_LENGTH, (pdu.length - SmsCbHeader.PDU_HEADER_LENGTH) * 8 / 7); if (hasLanguageIndicator && mBody != null && mBody.length() > 2) { mLanguage = mBody.substring(0, 2); mBody = mBody.substring(3); } break; case SmsMessage.ENCODING_16BIT: int offset = SmsCbHeader.PDU_HEADER_LENGTH; if (hasLanguageIndicator && pdu.length >= SmsCbHeader.PDU_HEADER_LENGTH + 2) { mLanguage = GsmAlphabet.gsm7BitPackedToString(pdu, SmsCbHeader.PDU_HEADER_LENGTH, 2); offset += 2; } try { mBody = new String(pdu, offset, (pdu.length & 0xfffe) - offset, "utf-16"); } catch (UnsupportedEncodingException e) { // Eeeek } break; default: break; } if (mBody != null) { // Remove trailing carriage return for (int i = mBody.length() - 1; i >= 0; i--) { if (mBody.charAt(i) != CARRIAGE_RETURN) { mBody = mBody.substring(0, i + 1); break; } } } else { mBody = ""; } } } telephony/java/android/telephony/SmsManager.java +61 −1 Original line number Diff line number Diff line Loading @@ -343,6 +343,66 @@ public final class SmsManager { return createMessageListFromRawRecords(records); } /** * Enable reception of cell broadcast (SMS-CB) messages with the given * message identifier. Note that if two different clients enable the same * message identifier, they must both disable it for the device to stop * receiving those messages. All received messages will be broadcast in an * intent with the action "android.provider.telephony.SMS_CB_RECEIVED". * Note: This call is blocking, callers may want to avoid calling it from * the main thread of an application. * * @param messageIdentifier Message identifier as specified in TS 23.041 * @return true if successful, false otherwise * @see #disableCellBroadcast(int) * * {@hide} */ public boolean enableCellBroadcast(int messageIdentifier) { boolean success = false; try { ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); if (iccISms != null) { success = iccISms.enableCellBroadcast(messageIdentifier); } } catch (RemoteException ex) { // ignore it } return success; } /** * Disable reception of cell broadcast (SMS-CB) messages with the given * message identifier. Note that if two different clients enable the same * message identifier, they must both disable it for the device to stop * receiving those messages. * Note: This call is blocking, callers may want to avoid calling it from * the main thread of an application. * * @param messageIdentifier Message identifier as specified in TS 23.041 * @return true if successful, false otherwise * * @see #enableCellBroadcast(int) * * {@hide} */ public boolean disableCellBroadcast(int messageIdentifier) { boolean success = false; try { ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); if (iccISms != null) { success = iccISms.disableCellBroadcast(messageIdentifier); } } catch (RemoteException ex) { // ignore it } return success; } /** * Create a list of <code>SmsMessage</code>s from a list of RawSmsData * records returned by <code>getAllMessagesFromIcc()</code> Loading telephony/java/com/android/internal/telephony/ISms.aidl +26 −0 Original line number Diff line number Diff line Loading @@ -144,4 +144,30 @@ interface ISms { in List<String> parts, in List<PendingIntent> sentIntents, in List<PendingIntent> deliveryIntents); /** * Enable reception of cell broadcast (SMS-CB) messages with the given * message identifier. Note that if two different clients enable the same * message identifier, they must both disable it for the device to stop * receiving those messages. * * @param messageIdentifier Message identifier as specified in TS 23.041 * @return true if successful, false otherwise * * @see #disableCellBroadcast(int) */ boolean enableCellBroadcast(int messageIdentifier); /** * Disable reception of cell broadcast (SMS-CB) messages with the given * message identifier. Note that if two different clients enable the same * message identifier, they must both disable it for the device to stop * receiving those messages. * * @param messageIdentifier Message identifier as specified in TS 23.041 * @return true if successful, false otherwise * * @see #enableCellBroadcast(int) */ boolean disableCellBroadcast(int messageIdentifier); } telephony/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java +8 −0 Original line number Diff line number Diff line Loading @@ -68,4 +68,12 @@ public class IccSmsInterfaceManagerProxy extends ISms.Stub { parts, sentIntents, deliveryIntents); } public boolean enableCellBroadcast(int messageIdentifier) throws android.os.RemoteException { return mIccSmsInterfaceManager.enableCellBroadcast(messageIdentifier); } public boolean disableCellBroadcast(int messageIdentifier) throws android.os.RemoteException { return mIccSmsInterfaceManager.disableCellBroadcast(messageIdentifier); } } telephony/java/com/android/internal/telephony/SMSDispatcher.java +19 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,9 @@ public abstract class SMSDispatcher extends Handler { /** Radio is ON */ static final protected int EVENT_RADIO_ON = 12; /** New broadcast SMS */ static final protected int EVENT_NEW_BROADCAST_SMS = 13; protected Phone mPhone; protected Context mContext; protected ContentResolver mResolver; Loading Loading @@ -399,6 +402,9 @@ public abstract class SMSDispatcher extends Handler { mCm.reportSmsMemoryStatus(mStorageAvailable, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE)); } case EVENT_NEW_BROADCAST_SMS: handleBroadcastSms((AsyncResult)msg.obj); break; } } Loading Loading @@ -995,4 +1001,17 @@ public abstract class SMSDispatcher extends Handler { } }; protected abstract void handleBroadcastSms(AsyncResult ar); protected void dispatchBroadcastPdus(byte[][] pdus) { Intent intent = new Intent("android.provider.telephony.SMS_CB_RECEIVED"); intent.putExtra("pdus", pdus); if (Config.LOGD) Log.d(TAG, "Dispatching " + pdus.length + " SMS CB pdus"); dispatch(intent, "android.permission.RECEIVE_SMS"); } } Loading
telephony/java/android/telephony/SmsCbMessage.java 0 → 100644 +267 −0 Original line number Diff line number Diff line /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.telephony; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.gsm.SmsCbHeader; import java.io.UnsupportedEncodingException; /** * Describes an SMS-CB message. * * {@hide} */ public class SmsCbMessage { /** * Cell wide immediate geographical scope */ public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0; /** * PLMN wide geographical scope */ public static final int GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1; /** * Location / service area wide geographical scope */ public static final int GEOGRAPHICAL_SCOPE_LA_WIDE = 2; /** * Cell wide geographical scope */ public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE = 3; /** * Create an instance of this class from a received PDU * * @param pdu PDU bytes * @return An instance of this class, or null if invalid pdu */ public static SmsCbMessage createFromPdu(byte[] pdu) { try { return new SmsCbMessage(pdu); } catch (IllegalArgumentException e) { return null; } } /** * Languages in the 0000xxxx DCS group as defined in 3GPP TS 23.038, section 5. */ private static final String[] LANGUAGE_CODES_GROUP_0 = { "de", "en", "it", "fr", "es", "nl", "sv", "da", "pt", "fi", "no", "el", "tr", "hu", "pl", null }; /** * Languages in the 0010xxxx DCS group as defined in 3GPP TS 23.038, section 5. */ private static final String[] LANGUAGE_CODES_GROUP_2 = { "cs", "he", "ar", "ru", "is", null, null, null, null, null, null, null, null, null, null, null }; private static final char CARRIAGE_RETURN = 0x0d; private SmsCbHeader mHeader; private String mLanguage; private String mBody; private SmsCbMessage(byte[] pdu) throws IllegalArgumentException { mHeader = new SmsCbHeader(pdu); parseBody(pdu); } /** * Return the geographical scope of this message, one of * {@link #GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE}, * {@link #GEOGRAPHICAL_SCOPE_PLMN_WIDE}, * {@link #GEOGRAPHICAL_SCOPE_LA_WIDE}, * {@link #GEOGRAPHICAL_SCOPE_CELL_WIDE} * * @return Geographical scope */ public int getGeographicalScope() { return mHeader.geographicalScope; } /** * Get the ISO-639-1 language code for this message, or null if unspecified * * @return Language code */ public String getLanguageCode() { return mLanguage; } /** * Get the body of this message, or null if no body available * * @return Body, or null */ public String getMessageBody() { return mBody; } /** * Get the message identifier of this message (0-65535) * * @return Message identifier */ public int getMessageIdentifier() { return mHeader.messageIdentifier; } /** * Get the message code of this message (0-1023) * * @return Message code */ public int getMessageCode() { return mHeader.messageCode; } /** * Get the update number of this message (0-15) * * @return Update number */ public int getUpdateNumber() { return mHeader.updateNumber; } private void parseBody(byte[] pdu) { int encoding; boolean hasLanguageIndicator = false; // Extract encoding and language from DCS, as defined in 3gpp TS 23.038, // section 5. switch ((mHeader.dataCodingScheme & 0xf0) >> 4) { case 0x00: encoding = SmsMessage.ENCODING_7BIT; mLanguage = LANGUAGE_CODES_GROUP_0[mHeader.dataCodingScheme & 0x0f]; break; case 0x01: hasLanguageIndicator = true; if ((mHeader.dataCodingScheme & 0x0f) == 0x01) { encoding = SmsMessage.ENCODING_16BIT; } else { encoding = SmsMessage.ENCODING_7BIT; } break; case 0x02: encoding = SmsMessage.ENCODING_7BIT; mLanguage = LANGUAGE_CODES_GROUP_2[mHeader.dataCodingScheme & 0x0f]; break; case 0x03: encoding = SmsMessage.ENCODING_7BIT; break; case 0x04: case 0x05: switch ((mHeader.dataCodingScheme & 0x0c) >> 2) { case 0x01: encoding = SmsMessage.ENCODING_8BIT; break; case 0x02: encoding = SmsMessage.ENCODING_16BIT; break; case 0x00: default: encoding = SmsMessage.ENCODING_7BIT; break; } break; case 0x06: case 0x07: // Compression not supported case 0x09: // UDH structure not supported case 0x0e: // Defined by the WAP forum not supported encoding = SmsMessage.ENCODING_UNKNOWN; break; case 0x0f: if (((mHeader.dataCodingScheme & 0x04) >> 2) == 0x01) { encoding = SmsMessage.ENCODING_8BIT; } else { encoding = SmsMessage.ENCODING_7BIT; } break; default: // Reserved values are to be treated as 7-bit encoding = SmsMessage.ENCODING_7BIT; break; } switch (encoding) { case SmsMessage.ENCODING_7BIT: mBody = GsmAlphabet.gsm7BitPackedToString(pdu, SmsCbHeader.PDU_HEADER_LENGTH, (pdu.length - SmsCbHeader.PDU_HEADER_LENGTH) * 8 / 7); if (hasLanguageIndicator && mBody != null && mBody.length() > 2) { mLanguage = mBody.substring(0, 2); mBody = mBody.substring(3); } break; case SmsMessage.ENCODING_16BIT: int offset = SmsCbHeader.PDU_HEADER_LENGTH; if (hasLanguageIndicator && pdu.length >= SmsCbHeader.PDU_HEADER_LENGTH + 2) { mLanguage = GsmAlphabet.gsm7BitPackedToString(pdu, SmsCbHeader.PDU_HEADER_LENGTH, 2); offset += 2; } try { mBody = new String(pdu, offset, (pdu.length & 0xfffe) - offset, "utf-16"); } catch (UnsupportedEncodingException e) { // Eeeek } break; default: break; } if (mBody != null) { // Remove trailing carriage return for (int i = mBody.length() - 1; i >= 0; i--) { if (mBody.charAt(i) != CARRIAGE_RETURN) { mBody = mBody.substring(0, i + 1); break; } } } else { mBody = ""; } } }
telephony/java/android/telephony/SmsManager.java +61 −1 Original line number Diff line number Diff line Loading @@ -343,6 +343,66 @@ public final class SmsManager { return createMessageListFromRawRecords(records); } /** * Enable reception of cell broadcast (SMS-CB) messages with the given * message identifier. Note that if two different clients enable the same * message identifier, they must both disable it for the device to stop * receiving those messages. All received messages will be broadcast in an * intent with the action "android.provider.telephony.SMS_CB_RECEIVED". * Note: This call is blocking, callers may want to avoid calling it from * the main thread of an application. * * @param messageIdentifier Message identifier as specified in TS 23.041 * @return true if successful, false otherwise * @see #disableCellBroadcast(int) * * {@hide} */ public boolean enableCellBroadcast(int messageIdentifier) { boolean success = false; try { ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); if (iccISms != null) { success = iccISms.enableCellBroadcast(messageIdentifier); } } catch (RemoteException ex) { // ignore it } return success; } /** * Disable reception of cell broadcast (SMS-CB) messages with the given * message identifier. Note that if two different clients enable the same * message identifier, they must both disable it for the device to stop * receiving those messages. * Note: This call is blocking, callers may want to avoid calling it from * the main thread of an application. * * @param messageIdentifier Message identifier as specified in TS 23.041 * @return true if successful, false otherwise * * @see #enableCellBroadcast(int) * * {@hide} */ public boolean disableCellBroadcast(int messageIdentifier) { boolean success = false; try { ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); if (iccISms != null) { success = iccISms.disableCellBroadcast(messageIdentifier); } } catch (RemoteException ex) { // ignore it } return success; } /** * Create a list of <code>SmsMessage</code>s from a list of RawSmsData * records returned by <code>getAllMessagesFromIcc()</code> Loading
telephony/java/com/android/internal/telephony/ISms.aidl +26 −0 Original line number Diff line number Diff line Loading @@ -144,4 +144,30 @@ interface ISms { in List<String> parts, in List<PendingIntent> sentIntents, in List<PendingIntent> deliveryIntents); /** * Enable reception of cell broadcast (SMS-CB) messages with the given * message identifier. Note that if two different clients enable the same * message identifier, they must both disable it for the device to stop * receiving those messages. * * @param messageIdentifier Message identifier as specified in TS 23.041 * @return true if successful, false otherwise * * @see #disableCellBroadcast(int) */ boolean enableCellBroadcast(int messageIdentifier); /** * Disable reception of cell broadcast (SMS-CB) messages with the given * message identifier. Note that if two different clients enable the same * message identifier, they must both disable it for the device to stop * receiving those messages. * * @param messageIdentifier Message identifier as specified in TS 23.041 * @return true if successful, false otherwise * * @see #enableCellBroadcast(int) */ boolean disableCellBroadcast(int messageIdentifier); }
telephony/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java +8 −0 Original line number Diff line number Diff line Loading @@ -68,4 +68,12 @@ public class IccSmsInterfaceManagerProxy extends ISms.Stub { parts, sentIntents, deliveryIntents); } public boolean enableCellBroadcast(int messageIdentifier) throws android.os.RemoteException { return mIccSmsInterfaceManager.enableCellBroadcast(messageIdentifier); } public boolean disableCellBroadcast(int messageIdentifier) throws android.os.RemoteException { return mIccSmsInterfaceManager.disableCellBroadcast(messageIdentifier); } }
telephony/java/com/android/internal/telephony/SMSDispatcher.java +19 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,9 @@ public abstract class SMSDispatcher extends Handler { /** Radio is ON */ static final protected int EVENT_RADIO_ON = 12; /** New broadcast SMS */ static final protected int EVENT_NEW_BROADCAST_SMS = 13; protected Phone mPhone; protected Context mContext; protected ContentResolver mResolver; Loading Loading @@ -399,6 +402,9 @@ public abstract class SMSDispatcher extends Handler { mCm.reportSmsMemoryStatus(mStorageAvailable, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE)); } case EVENT_NEW_BROADCAST_SMS: handleBroadcastSms((AsyncResult)msg.obj); break; } } Loading Loading @@ -995,4 +1001,17 @@ public abstract class SMSDispatcher extends Handler { } }; protected abstract void handleBroadcastSms(AsyncResult ar); protected void dispatchBroadcastPdus(byte[][] pdus) { Intent intent = new Intent("android.provider.telephony.SMS_CB_RECEIVED"); intent.putExtra("pdus", pdus); if (Config.LOGD) Log.d(TAG, "Dispatching " + pdus.length + " SMS CB pdus"); dispatch(intent, "android.permission.RECEIVE_SMS"); } }