SMSDispatcher.java revision e70617d81dcd42350a737b11c25532e1d43df4ff
10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/* 20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2006 The Android Open Source Project 30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License. 60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at 70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * http://www.apache.org/licenses/LICENSE-2.0 90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software 110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS, 120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and 140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License. 150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony; 180825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.Activity; 190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.AlertDialog; 200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.PendingIntent; 210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.PendingIntent.CanceledException; 220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.ContentResolver; 230217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.content.ContentValues; 240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Context; 250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.DialogInterface; 260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Intent; 270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.ApplicationInfo; 282029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condraimport android.content.pm.PackageInfo; 290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.PackageManager; 300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.res.Resources; 31ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwaltimport android.database.ContentObserver; 320217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.database.sqlite.SqliteWrapper; 330217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.net.Uri; 340825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult; 350825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Binder; 360825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler; 370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message; 388215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.os.RemoteException; 390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.SystemProperties; 40ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwaltimport android.provider.Settings; 410217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.provider.Telephony; 420217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.provider.Telephony.Sms; 438215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.service.carrier.CarrierMessagingService; 448215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.service.carrier.ICarrierMessagingCallback; 458215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.service.carrier.ICarrierMessagingService; 468215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.telephony.CarrierMessagingServiceManager; 470825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.PhoneNumberUtils; 480d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.Rlog; 490825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.ServiceState; 500825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.TelephonyManager; 510825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.Html; 520825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.Spanned; 53b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.text.TextUtils; 542029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condraimport android.util.EventLog; 554658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.view.LayoutInflater; 564658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.view.View; 5778df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwaltimport android.view.ViewGroup; 580825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.WindowManager; 594658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.Button; 604658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.CheckBox; 614658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.CompoundButton; 624658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.TextView; 630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 640825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.R; 650825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; 66a9552aa6bf3ce12c75ad43165034d9a1233fb131Shishir Agrawalimport com.android.internal.telephony.uicc.UiccCard; 67c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport com.android.internal.telephony.uicc.UiccController; 680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 690825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList; 700825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.HashMap; 718d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport java.util.List; 720825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Random; 73c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport java.util.concurrent.atomic.AtomicBoolean; 740d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.util.concurrent.atomic.AtomicInteger; 750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 760825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE; 770825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_GENERIC_FAILURE; 780825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_LIMIT_EXCEEDED; 790825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_NO_SERVICE; 800825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_NULL_PDU; 810825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_RADIO_OFF; 820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 830825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic abstract class SMSDispatcher extends Handler { 84cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville static final String TAG = "SMSDispatcher"; // accessed from inner class 85cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville static final boolean DBG = false; 860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String SEND_NEXT_MSG_EXTRA = "SendNextMsg"; 870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Permission required to send SMS to short codes without user confirmation. */ 890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String SEND_SMS_NO_CONFIRMATION_PERMISSION = 900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "android.permission.SEND_SMS_NO_CONFIRMATION"; 910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 92ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private static final int PREMIUM_RULE_USE_SIM = 1; 93ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private static final int PREMIUM_RULE_USE_NETWORK = 2; 94ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private static final int PREMIUM_RULE_USE_BOTH = 3; 95ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private final AtomicInteger mPremiumSmsRule = new AtomicInteger(PREMIUM_RULE_USE_SIM); 96ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private final SettingsObserver mSettingsObserver; 97ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** SMS send complete. */ 990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final int EVENT_SEND_SMS_COMPLETE = 2; 1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Retry sending a previously failed SMS message */ 1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_SEND_RETRY = 3; 1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Confirmation required for sending a large number of messages. */ 1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_SEND_LIMIT_REACHED_CONFIRMATION = 4; 1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Send the user confirmed SMS */ 1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville static final int EVENT_SEND_CONFIRMED_SMS = 5; // accessed from inner class 1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Don't send SMS (user did not confirm). */ 1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville static final int EVENT_STOP_SENDING = 7; // accessed from inner class 1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Confirmation required for third-party apps sending to an SMS short code. */ 1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE = 8; 1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Confirmation required for third-party apps sending to an SMS short code. */ 1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE = 9; 1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1190d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** Handle status report from {@code CdmaInboundSmsHandler}. */ 1200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby protected static final int EVENT_HANDLE_STATUS_REPORT = 10; 1210d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 1221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** Radio is ON */ 1231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_RADIO_ON = 11; 1241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1251260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** IMS registration/SMS format changed */ 1261260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_IMS_STATE_CHANGED = 12; 1271260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1281260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** Callback from RIL_REQUEST_IMS_REGISTRATION_STATE */ 1291260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_IMS_STATE_DONE = 13; 1301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1311260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // other 1321260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_NEW_ICC_SMS = 14; 1331260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_ICC_CHANGED = 15; 1341260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1351260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected PhoneBase mPhone; 1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected final Context mContext; 1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected final ContentResolver mResolver; 13822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville protected final CommandsInterface mCi; 1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected final TelephonyManager mTelephonyManager; 1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Maximum number of times to retry sending a failed SMS. */ 1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int MAX_SEND_RETRIES = 3; 1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Delay before next send attempt on a failed SMS, in milliseconds. */ 1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int SEND_RETRY_DELAY = 2000; 1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** single part SMS */ 1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int SINGLE_PART_SMS = 1; 1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Message sending queue limit */ 1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int MO_MSG_QUEUE_LIMIT = 5; 1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Message reference for a CONCATENATED_8_BIT_REFERENCE or 1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * CONCATENATED_16_BIT_REFERENCE message set. Should be 1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * incremented for each set of concatenated messages. 1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Static field shared by all dispatcher objects. 1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static int sConcatenatedRef = new Random().nextInt(256); 1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Outgoing message counter. Shared by all dispatchers. */ 1591260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa private SmsUsageMonitor mUsageMonitor; 1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 161ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa private ImsSMSDispatcher mImsSMSDispatcher; 162ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa 1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Number of outgoing SmsTrackers waiting for user confirmation. */ 1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private int mPendingTrackerCount; 1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* Flags indicating whether the current device allows sms service */ 1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected boolean mSmsCapable = true; 1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected boolean mSmsSendDisabled; 1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static int getNextConcatenatedRef() { 1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sConcatenatedRef += 1; 1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return sConcatenatedRef; 1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Create a new SMS dispatcher. 1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param phone the Phone to use 1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param usageMonitor the SmsUsageMonitor to use 1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 180ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected SMSDispatcher(PhoneBase phone, SmsUsageMonitor usageMonitor, 181ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa ImsSMSDispatcher imsSMSDispatcher) { 1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhone = phone; 183ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa mImsSMSDispatcher = imsSMSDispatcher; 1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mContext = phone.getContext(); 1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mResolver = mContext.getContentResolver(); 18622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi = phone.mCi; 1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mUsageMonitor = usageMonitor; 1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 189ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mSettingsObserver = new SettingsObserver(this, mPremiumSmsRule, mContext); 190ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor( 191ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt Settings.Global.SMS_SHORT_CODE_RULE), false, mSettingsObserver); 1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mSmsCapable = mContext.getResources().getBoolean( 1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville com.android.internal.R.bool.config_sms_capable); 195e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu mSmsSendDisabled = !mTelephonyManager.getSmsSendCapableForPhone( 196e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu mPhone.getPhoneId(), mSmsCapable); 197ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "SMSDispatcher: ctor mSmsCapable=" + mSmsCapable + " format=" + getFormat() 1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville + " mSmsSendDisabled=" + mSmsSendDisabled); 1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 201ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt /** 202ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt * Observe the secure setting for updated premium sms determination rules 203ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt */ 204ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private static class SettingsObserver extends ContentObserver { 205ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private final AtomicInteger mPremiumSmsRule; 206ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private final Context mContext; 207ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt SettingsObserver(Handler handler, AtomicInteger premiumSmsRule, Context context) { 208ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt super(handler); 209ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mPremiumSmsRule = premiumSmsRule; 210ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mContext = context; 211ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt onChange(false); // load initial value; 212ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 213ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 214ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt @Override 215ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt public void onChange(boolean selfChange) { 216ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mPremiumSmsRule.set(Settings.Global.getInt(mContext.getContentResolver(), 217ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt Settings.Global.SMS_SHORT_CODE_RULE, PREMIUM_RULE_USE_SIM)); 218ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 219ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 220ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 2211260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected void updatePhoneObject(PhoneBase phone) { 2221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mPhone = phone; 2231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mUsageMonitor = phone.mSmsUsageMonitor; 2241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa Rlog.d(TAG, "Active phone changed to " + mPhone.getPhoneName() ); 2251260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 2261260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Unregister for incoming SMS events. */ 2280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby public void dispose() { 2290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); 2300d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The format of the message PDU in the associated broadcast intent. 2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * This will be either "3gpp" for GSM/UMTS/LTE messages in 3GPP format 2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or "3gpp2" for CDMA/LTE messages in 3GPP2 format. 2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Note: All applications which handle incoming SMS messages by processing the 2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * SMS_RECEIVED_ACTION broadcast intent MUST pass the "format" extra from the intent 2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * into the new methods in {@link android.telephony.SmsMessage} which take an 2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * extra format parameter. This is required in order to correctly decode the PDU on 2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * devices which require support for both 3GPP and 3GPP2 formats at the same time, 2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * such as CDMA/LTE devices and GSM/CDMA world phones. 2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return the format of the message PDU 2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract String getFormat(); 2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 2490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Pass the Message object to subclass to handle. Currently used to pass CDMA status reports 2500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * from {@link com.android.internal.telephony.cdma.CdmaInboundSmsHandler}. 2510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @param o the SmsMessage containing the status report 2520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 2530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby protected void handleStatusReport(Object o) { 2540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.d(TAG, "handleStatusReport() called with no subclass."); 2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* TODO: Need to figure out how to keep track of status report routing in a 2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * persistent manner. If the phone process restarts (reboot or crash), 2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * we will lose this list and any status reports that come in after 2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * will be dropped. 2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Sent messages awaiting a delivery status report. */ 2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected final ArrayList<SmsTracker> deliveryPendingList = new ArrayList<SmsTracker>(); 2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Handles events coming from the phone stack. Overridden from handler. 2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param msg the message to handle 2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void handleMessage(Message msg) { 2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (msg.what) { 2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_SMS_COMPLETE: 2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // An outbound SMS has been successfully transferred, or failed. 2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleSendComplete((AsyncResult) msg.obj); 2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_RETRY: 2791260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa Rlog.d(TAG, "SMS retry.."); 2801260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa sendRetrySms((SmsTracker) msg.obj); 2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_LIMIT_REACHED_CONFIRMATION: 2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleReachSentLimit((SmsTracker)(msg.obj)); 2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE: 2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleConfirmShortCode(false, (SmsTracker)(msg.obj)); 2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE: 2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleConfirmShortCode(true, (SmsTracker)(msg.obj)); 2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_CONFIRMED_SMS: 2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsTracker tracker = (SmsTracker) msg.obj; 2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (tracker.isMultipart()) { 2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMultipartSms(tracker); 3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 3016c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying if (mPendingTrackerCount > 1) { 3026c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying tracker.mExpectMore = true; 3036c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying } else { 3046c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying tracker.mExpectMore = false; 3056c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying } 3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendSms(tracker); 3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPendingTrackerCount--; 3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_STOP_SENDING: 3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsTracker tracker = (SmsTracker) msg.obj; 315c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_LIMIT_EXCEEDED, 0/*errorCode*/); 3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPendingTrackerCount--; 3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby case EVENT_HANDLE_STATUS_REPORT: 3210d4bcdf379842af4b6304809156971e926f374f0Jake Hamby handleStatusReport(msg.obj); 3220d4bcdf379842af4b6304809156971e926f374f0Jake Hamby break; 3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3240d4bcdf379842af4b6304809156971e926f374f0Jake Hamby default: 3250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.e(TAG, "handleMessage() ignoring message of unexpected type " + msg.what); 3260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 327b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby } 328b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby 329b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby /** 3308215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Use the carrier messaging service to send a data or text SMS. 3318215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 3328215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected abstract class SmsSender extends CarrierMessagingServiceManager { 3338215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected final SmsTracker mTracker; 3348215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang // Initialized in sendSmsByCarrierApp 3358215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected volatile SmsSenderCallback mSenderCallback; 3368215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 3378215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected SmsSender(SmsTracker tracker) { 3388215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mTracker = tracker; 3398215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3408215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 3418215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void sendSmsByCarrierApp(String carrierPackageName, 3428215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang SmsSenderCallback senderCallback) { 3438215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback = senderCallback; 3448215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (!bindToCarrierMessagingService(mContext, carrierPackageName)) { 3458215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "bindService() for carrier messaging service failed"); 3468215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendSmsComplete( 3478215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 3488215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 0 /* messageRef */); 3498215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } else { 3508215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "bindService() for carrier messaging service succeeded"); 3518215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3528215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3538215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3548215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 3558215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 3568215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Use the carrier messaging service to send a text SMS. 3578215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 3588215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected final class TextSmsSender extends SmsSender { 3598215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public TextSmsSender(SmsTracker tracker) { 3608215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang super(tracker); 3618215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3628215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 3638215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 3648215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected void onServiceReady(ICarrierMessagingService carrierMessagingService) { 3658215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang HashMap<String, Object> map = mTracker.mData; 3668215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang String text = (String) map.get("text"); 3678215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 3688215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (text != null) { 3698215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang try { 3708215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang carrierMessagingService.sendTextSms(text, getSubId(), 3718215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mTracker.mDestAddress, mSenderCallback); 3728215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } catch (RemoteException e) { 3738215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Exception sending the SMS: " + e); 3748215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendSmsComplete( 3758215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 3768215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 0 /* messageRef */); 3778215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3788215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } else { 3798215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendSmsComplete( 3808215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 3818215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 0 /* messageRef */); 3828215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3838215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3848215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3858215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 3868215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 3878215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Use the carrier messaging service to send a data SMS. 3888215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 3898215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected final class DataSmsSender extends SmsSender { 3908215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public DataSmsSender(SmsTracker tracker) { 3918215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang super(tracker); 3928215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3938215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 3948215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 3958215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected void onServiceReady(ICarrierMessagingService carrierMessagingService) { 3968215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang HashMap<String, Object> map = mTracker.mData; 3978215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang byte[] data = (byte[]) map.get("data"); 3988215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang int destPort = (int) map.get("destPort"); 3998215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4008215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (data != null) { 4018215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang try { 4028215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang carrierMessagingService.sendDataSms(data, getSubId(), 4038215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mTracker.mDestAddress, destPort, mSenderCallback); 4048215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } catch (RemoteException e) { 4058215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Exception sending the SMS: " + e); 4068215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendSmsComplete( 4078215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 4088215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 0 /* messageRef */); 4098215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4108215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } else { 4118215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendSmsComplete( 4128215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 4138215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 0 /* messageRef */); 4148215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4158215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4168215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4178215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4188215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 4198215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Callback for TextSmsSender and DataSmsSender from the carrier messaging service. 4208215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Once the result is ready, the carrier messaging service connection is disposed. 4218215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 4228215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected final class SmsSenderCallback extends ICarrierMessagingCallback.Stub { 4238215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private final SmsSender mSmsSender; 4248215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4258215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public SmsSenderCallback(SmsSender smsSender) { 4268215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSmsSender = smsSender; 4278215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4288215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4298215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 4308215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * This method should be called only once. 4318215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 4328215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 4338215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onSendSmsComplete(int result, int messageRef) { 4348215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSmsSender.disposeConnection(mContext); 4358215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang processSendSmsResponse(mSmsSender.mTracker, result, messageRef); 4368215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4378215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4388215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 4398215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onSendMultipartSmsComplete(int result, int[] messageRefs) { 4408215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onSendMultipartSmsComplete call with result: " + result); 4418215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4428215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4438215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 4448215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onFilterComplete(boolean keepMessage) { 4458215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onFilterComplete call with result: " + keepMessage); 4468215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4478215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4488215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 4498215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onSendMmsComplete(int result, byte[] sendConfPdu) { 4508215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onSendMmsComplete call with result: " + result); 4518215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4528215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4538215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 4548215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onDownloadMmsComplete(int result) { 4558215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onDownloadMmsComplete call with result: " + result); 4568215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4578215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4588215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4598215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private void processSendSmsResponse(SmsTracker tracker, int result, int messageRef) { 4608215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (tracker == null) { 4618215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "processSendSmsResponse: null tracker"); 4628215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang return; 4638215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4648215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4658215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang SmsResponse smsResponse = new SmsResponse( 4668215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang messageRef, null /* ackPdu */, -1 /* unknown error code */); 4678215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4688215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang switch (result) { 4698215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang case CarrierMessagingService.SEND_STATUS_OK: 4708215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "Sending SMS by IP succeeded."); 4718215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE, 4728215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang new AsyncResult(tracker, 4738215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang smsResponse, 4748215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang null /* exception*/ ))); 4758215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang break; 4768215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang case CarrierMessagingService.SEND_STATUS_ERROR: 4778215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "Sending SMS by IP failed."); 4788215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE, 4798215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang new AsyncResult(tracker, smsResponse, 4808215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang new CommandException(CommandException.Error.GENERIC_FAILURE)))); 4818215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang break; 4828215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang case CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK: 4838215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "Sending SMS by IP failed. Retry on carrier network."); 4848215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang sendSubmitPdu(tracker); 4858215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang break; 4868215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang default: 4878215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "Unknown result " + result + " Retry on carrier network."); 4888215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang sendSubmitPdu(tracker); 4898215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4908215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4918215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4928215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 4938215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Use the carrier messaging service to send a multipart text SMS. 4948215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 4958215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private final class MultipartSmsSender extends CarrierMessagingServiceManager { 4968215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private final List<String> mParts; 4978215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public final SmsTracker[] mTrackers; 4988215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang // Initialized in sendSmsByCarrierApp 4998215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private volatile MultipartSmsSenderCallback mSenderCallback; 5008215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5018215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang MultipartSmsSender(ArrayList<String> parts, SmsTracker[] trackers) { 5028215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mParts = parts; 5038215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mTrackers = trackers; 5048215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5058215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5068215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang void sendSmsByCarrierApp(String carrierPackageName, 5078215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang MultipartSmsSenderCallback senderCallback) { 5088215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback = senderCallback; 5098215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (!bindToCarrierMessagingService(mContext, carrierPackageName)) { 5108215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "bindService() for carrier messaging service failed"); 5118215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendMultipartSmsComplete( 5128215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 5138215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang null /* smsResponse */); 5148215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } else { 5158215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "bindService() for carrier messaging service succeeded"); 5168215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5178215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5188215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5198215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 5208215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected void onServiceReady(ICarrierMessagingService carrierMessagingService) { 5218215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang try { 5228215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang carrierMessagingService.sendMultipartTextSms( 5238215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mParts, getSubId(), mTrackers[0].mDestAddress, mSenderCallback); 5248215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } catch (RemoteException e) { 5258215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Exception sending the SMS: " + e); 5268215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendMultipartSmsComplete( 5278215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 5288215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang null /* smsResponse */); 5298215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5308215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5318215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5328215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5338215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 5348215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Callback for MultipartSmsSender from the carrier messaging service. 5358215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Once the result is ready, the carrier messaging service connection is disposed. 5368215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 5378215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private final class MultipartSmsSenderCallback extends ICarrierMessagingCallback.Stub { 5388215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private final MultipartSmsSender mSmsSender; 5398215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5408215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang MultipartSmsSenderCallback(MultipartSmsSender smsSender) { 5418215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSmsSender = smsSender; 5428215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5438215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5448215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 5458215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onSendSmsComplete(int result, int messageRef) { 5468215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onSendSmsComplete call with result: " + result); 5478215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5488215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5498215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 5508215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * This method should be called only once. 5518215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 5528215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 5538215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onSendMultipartSmsComplete(int result, int[] messageRefs) { 5548215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSmsSender.disposeConnection(mContext); 5558215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5568215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (mSmsSender.mTrackers == null) { 5578215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onSendMultipartSmsComplete call with null trackers."); 5588215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang return; 5598215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5608215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5618215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang for (int i = 0; i < mSmsSender.mTrackers.length; i++) { 5628215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang int messageRef = 0; 5638215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (messageRefs != null && messageRefs.length > i) { 5648215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang messageRef = messageRefs[i]; 5658215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5668215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang processSendSmsResponse(mSmsSender.mTrackers[i], result, messageRef); 5678215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5688215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5698215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5708215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 5718215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onFilterComplete(boolean keepMessage) { 5728215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onFilterComplete call with result: " + keepMessage); 5738215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5748215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5758215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 5768215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onSendMmsComplete(int result, byte[] sendConfPdu) { 5778215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onSendMmsComplete call with result: " + result); 5788215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5798215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5808215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 5818215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onDownloadMmsComplete(int result) { 5828215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onDownloadMmsComplete call with result: " + result); 5838215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5848215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5858215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5868215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 5878215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Send an SMS PDU. Usually just calls {@link sendRawPdu}. 5888215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 5898215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected abstract void sendSubmitPdu(SmsTracker tracker); 5908215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5918215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Called when SMS send completes. Broadcasts a sentIntent on success. 5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * On failure, either sets up retries or broadcasts a sentIntent with 5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the failure in the result code. 5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param ar AsyncResult passed into the message handler. ar.result should 5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * an SmsResponse instance if send was successful. ar.userObj 5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * should be an SmsTracker instance. 5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void handleSendComplete(AsyncResult ar) { 6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsTracker tracker = (SmsTracker) ar.userObj; 6020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent sentIntent = tracker.mSentIntent; 6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 604454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks if (ar.result != null) { 6055a176f73dbb2bff2ca8b8f86af86a17be6863b87Wink Saville tracker.mMessageRef = ((SmsResponse)ar.result).mMessageRef; 606454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks } else { 607454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks Rlog.d(TAG, "SmsResponse was null"); 608454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks } 609454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks 6100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.exception == null) { 611cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville if (DBG) Rlog.d(TAG, "SMS send complete. Broadcasting intent: " + sentIntent); 6120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (tracker.mDeliveryIntent != null) { 6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Expecting a status report. Add it to the list. 6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville deliveryPendingList.add(tracker); 6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 617c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onSent(mContext); 6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 619cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville if (DBG) Rlog.d(TAG, "SMS send failed"); 6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int ss = mPhone.getServiceState().getState(); 6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if ( tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) { 6241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // This is retry after failure over IMS but voice is not available. 6251260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Set retry to max allowed, so no retry is sent and 6261260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // cause RESULT_ERROR_GENERIC_FAILURE to be returned to app. 6271260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa tracker.mRetryCount = MAX_SEND_RETRIES; 6281260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 6291260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa Rlog.d(TAG, "handleSendComplete: Skipping retry: " 6301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" isIms()="+isIms() 6311260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" mRetryCount="+tracker.mRetryCount 6321260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" mImsRetry="+tracker.mImsRetry 6331260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" mMessageRef="+tracker.mMessageRef 6341260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" SS= "+mPhone.getServiceState().getState()); 6351260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 6361260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 6371260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // if sms over IMS is not supported on data and voice is not available... 6381260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) { 639c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, getNotInServiceError(ss), 0/*errorCode*/); 6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if ((((CommandException)(ar.exception)).getCommandError() 6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville == CommandException.Error.SMS_FAIL_RETRY) && 6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tracker.mRetryCount < MAX_SEND_RETRIES) { 6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Retry after a delay if needed. 6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TODO: According to TS 23.040, 9.2.3.6, we should resend 6450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // with the same TP-MR as the failed message, and 6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TP-RD set to 1. However, we don't have a means of 6470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // knowing the MR for the failed message (EF_SMSstatus 6480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // may or may not have the MR corresponding to this 6490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // message, depending on the failure). Also, in some 6500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // implementations this retry is handled by the baseband. 6510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tracker.mRetryCount++; 6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker); 6530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessageDelayed(retryMsg, SEND_RETRY_DELAY); 654c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } else { 655c99dab56e20222b28cbc6238645feac938f1c333Ye Wen int errorCode = 0; 656c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (ar.result != null) { 657c99dab56e20222b28cbc6238645feac938f1c333Ye Wen errorCode = ((SmsResponse)ar.result).mErrorCode; 658c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int error = RESULT_ERROR_GENERIC_FAILURE; 6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (((CommandException)(ar.exception)).getCommandError() 6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville == CommandException.Error.FDN_CHECK_FAILURE) { 6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville error = RESULT_ERROR_FDN_CHECK_FAILURE; 6630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 664c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, error, errorCode); 6650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 6700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Handles outbound message when the phone is not in service. 6710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 6720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param ss Current service state. Valid values are: 6730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * OUT_OF_SERVICE 6740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * EMERGENCY_ONLY 6750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * POWER_OFF 6760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntent the PendingIntent to send the error to 6770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 6780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static void handleNotInService(int ss, PendingIntent sentIntent) { 6790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntent != null) { 6800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 6810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ss == ServiceState.STATE_POWER_OFF) { 6820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(RESULT_ERROR_RADIO_OFF); 6830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 6840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(RESULT_ERROR_NO_SERVICE); 6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CanceledException ex) {} 6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 691c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param ss service state 692c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @return The result error based on input service state for not in service error 693c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 694c99dab56e20222b28cbc6238645feac938f1c333Ye Wen protected static int getNotInServiceError(int ss) { 695c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (ss == ServiceState.STATE_POWER_OFF) { 696c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return RESULT_ERROR_RADIO_OFF; 697c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 698c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return RESULT_ERROR_NO_SERVICE; 699c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 700c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 701c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 7020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a data based SMS to a specific application port. 7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 7040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param destAddr the address to send the message to 7050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddr is the service center address or null to use 7060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the current default SMSC 7070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param destPort the port to deliver the message to 7080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param data the body of the message to send 7090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntent if not NULL this <code>PendingIntent</code> is 7100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is successfully sent, or failed. 7110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 7120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors:<br> 7130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 7140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code><br> 7150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code><br> 7160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code><br>. 7170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 7180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the extra "errorCode" containing a radio technology specific value, 7190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * generally only useful for troubleshooting.<br> 7200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 7210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 7220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 7230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 7240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is delivered to the recipient. The 7250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * raw pdu of the status report is in the extended data ("pdu"). 7260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 7270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract void sendData(String destAddr, String scAddr, int destPort, 7280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent); 7290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 7310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a text based SMS. 732b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param destAddr the address to send the message to 7330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddr is the service center address or null to use 7340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the current default SMSC 7350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param text the body of the message to send 7360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntent if not NULL this <code>PendingIntent</code> is 7370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is successfully sent, or failed. 7380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 7390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors:<br> 7400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 7410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code><br> 7420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code><br> 7430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code><br>. 7440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 7450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the extra "errorCode" containing a radio technology specific value, 7460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * generally only useful for troubleshooting.<br> 7470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 7480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 7490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 7500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 7510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is delivered to the recipient. The 752b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param messageUri optional URI of the message if it is already stored in the system 753b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param callingPkg the calling package name 7540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 755b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen protected abstract void sendText(String destAddr, String scAddr, String text, 756b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri, 757b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen String callingPkg); 7580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 76063418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * Inject an SMS PDU into the android platform. 76163418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * 76263418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * @param pdu is the byte array of pdu to be injected into android telephony layer 76363418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * @param format is the format of SMS pdu (3gpp or 3gpp2) 76463418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * @param receivedIntent if not NULL this <code>PendingIntent</code> is 76563418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * broadcast when the message is successfully received by the 76663418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * android telephony layer. This intent is broadcasted at 76763418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * the same time an SMS received from radio is responded back. 76863418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni */ 76963418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni protected abstract void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent); 77063418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni 77163418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni /** 7720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Calculate the number of septets needed to encode the message. 7730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 7740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param messageBody the message to encode 7750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param use7bitOnly ignore (but still count) illegal characters if true 7760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return TextEncodingDetails 7770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 7780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract TextEncodingDetails calculateLength(CharSequence messageBody, 7790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean use7bitOnly); 7800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 7820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a multi-part text based SMS. 783b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param destAddr the address to send the message to 7840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddr is the service center address or null to use 7850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the current default SMSC 7860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param parts an <code>ArrayList</code> of strings that, in order, 7870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * comprise the original message 7880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntents if not null, an <code>ArrayList</code> of 7890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>PendingIntent</code>s (one for each message part) that is 7900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the corresponding message part has been sent. 7910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 7920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors: 7930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code> 7940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code> 7950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code> 7960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code>. 7970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 7980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 7990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 8000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param deliveryIntents if not null, an <code>ArrayList</code> of 8010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>PendingIntent</code>s (one for each message part) that is 8020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the corresponding message part has been delivered 8030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * to the recipient. The raw pdu of the status report is in the 804b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param messageUri optional URI of the message if it is already stored in the system 805b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param callingPkg the calling package name 8060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void sendMultipartText(String destAddr, String scAddr, 8080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, 809b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg) { 8104bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final String fullMessageText = getMultipartMessageText(parts); 8110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int refNumber = getNextConcatenatedRef() & 0x00FF; 8120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int msgCount = parts.size(); 8130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int encoding = SmsConstants.ENCODING_UNKNOWN; 8140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount]; 8160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < msgCount; i++) { 8170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TextEncodingDetails details = calculateLength(parts.get(i), false); 8180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (encoding != details.codeUnitSize 8190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville && (encoding == SmsConstants.ENCODING_UNKNOWN 8200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville || encoding == SmsConstants.ENCODING_7BIT)) { 8210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encoding = details.codeUnitSize; 8220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodingForParts[i] = details; 8240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8268215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang SmsTracker[] trackers = new SmsTracker[msgCount]; 8278215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 828c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // States to track at the message level (for all parts) 829c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final AtomicInteger unsentPartCount = new AtomicInteger(msgCount); 830c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final AtomicBoolean anyPartFailed = new AtomicBoolean(false); 831c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 8320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < msgCount; i++) { 8330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); 8340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.refNumber = refNumber; 8350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.seqNumber = i + 1; // 1-based sequence 8360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.msgCount = msgCount; 8370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TODO: We currently set this to true since our messaging app will never 8380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // send more than 255 parts (it converts the message to MMS well before that). 8390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // However, we should support 3rd party messaging apps that might need 16-bit 8400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // references 8410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Note: It's not sufficient to just flip this bit to true; it will have 8420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // ripple effects (several calculations assume 8-bit ref). 8430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.isEightBits = true; 8440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsHeader smsHeader = new SmsHeader(); 8450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsHeader.concatRef = concatRef; 8460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Set the national language tables for 3GPP 7-bit encoding, if enabled. 8480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (encoding == SmsConstants.ENCODING_7BIT) { 8490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsHeader.languageTable = encodingForParts[i].languageTable; 8500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable; 8510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent sentIntent = null; 8540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntents != null && sentIntents.size() > i) { 8550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent = sentIntents.get(i); 8560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent deliveryIntent = null; 8590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (deliveryIntents != null && deliveryIntents.size() > i) { 8600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville deliveryIntent = deliveryIntents.get(i); 8610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8638215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang trackers[i] = 8648215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang getNewSubmitPduTracker(destAddr, scAddr, parts.get(i), smsHeader, encoding, 8658215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang sentIntent, deliveryIntent, (i == (msgCount - 1)), 8668215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang unsentPartCount, anyPartFailed, messageUri, fullMessageText); 8678215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 8688215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 8698215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (parts == null || trackers == null || trackers.length == 0 8708215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang || trackers[0] == null) { 8718215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Cannot send multipart text. parts=" + parts + " trackers=" + trackers); 8728215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang return; 8738215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 8748215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 8758215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang String carrierPackage = getCarrierAppPackageName(); 8768215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (carrierPackage != null) { 8778215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "Found carrier package."); 8788215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang MultipartSmsSender smsSender = new MultipartSmsSender(parts, trackers); 8798215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang smsSender.sendSmsByCarrierApp(carrierPackage, new MultipartSmsSenderCallback(smsSender)); 8808215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } else { 8818215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.v(TAG, "No carrier package."); 8828215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang for (SmsTracker tracker : trackers) { 8838215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (tracker != null) { 8848215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang sendSubmitPdu(tracker); 8858215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } else { 8868215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Null tracker."); 8878215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 8888215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 8890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8938215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Create a new SubmitPdu and return the SMS tracker. 8940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8958215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected abstract SmsTracker getNewSubmitPduTracker(String destinationAddress, String scAddress, 8960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String message, SmsHeader smsHeader, int encoding, 897c99dab56e20222b28cbc6238645feac938f1c333Ye Wen PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart, 8984bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, 8994bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen String fullMessageText); 9000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9028215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Send an SMS 9031260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * @param tracker will contain: 9041260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -smsc the SMSC to send the message through, or NULL for the 9050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * default SMSC 9061260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -pdu the raw PDU to send 9071260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -sentIntent if not NULL this <code>Intent</code> is 9080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is successfully sent, or failed. 9090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 9100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors: 9110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code> 9120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code> 9130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code> 9140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code>. 9150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 9160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 9170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 9181260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -deliveryIntent if not NULL this <code>Intent</code> is 9190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is delivered to the recipient. The 9200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * raw pdu of the status report is in the extended data ("pdu"). 9211260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -param destAddr the destination phone number (for short code confirmation) 9220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 9231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected void sendRawPdu(SmsTracker tracker) { 9241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa HashMap map = tracker.mData; 9251260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa byte pdu[] = (byte[]) map.get("pdu"); 9261260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 9270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mSmsSendDisabled) { 928c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Device does not support sending sms."); 929c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_NO_SERVICE, 0/*errorCode*/); 9300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 9310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (pdu == null) { 934c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Empty PDU"); 935c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_NULL_PDU, 0/*errorCode*/); 9360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 9370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Get calling app package name via UID from Binder call 9400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PackageManager pm = mContext.getPackageManager(); 9410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String[] packageNames = pm.getPackagesForUid(Binder.getCallingUid()); 9420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (packageNames == null || packageNames.length == 0) { 9440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Refuse to send SMS if we can't get the calling package name. 945ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get calling app package name: refusing to send SMS"); 946c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/); 9470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 9480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9502029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // Get package info via packagemanager 9510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby PackageInfo appInfo; 9522029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra try { 9532029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // XXX this is lossy- apps can share a UID 9542029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra appInfo = pm.getPackageInfo(packageNames[0], PackageManager.GET_SIGNATURES); 9552029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra } catch (PackageManager.NameNotFoundException e) { 956ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get calling app package info: refusing to send SMS"); 957c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/); 9582029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra return; 9592029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra } 9600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // checkDestination() returns true if the destination is not a premium short code or the 9620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // sending app is approved to send to short codes. Otherwise, a message is sent to our 9630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // handler with the SmsTracker to request user confirmation before sending. 9640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (checkDestination(tracker)) { 9650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // check for excessive outgoing SMS usage by this app 9662029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra if (!mUsageMonitor.check(appInfo.packageName, SINGLE_PART_SMS)) { 9670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, tracker)); 9680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 9690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 971a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal sendSms(tracker); 9720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Check if destination is a potential premium short code and sender is not pre-approved to 9770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * send to short codes. 9780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 9790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker the tracker for the SMS to send 9800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the destination is approved; false if user confirmation event was sent 9810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 9820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean checkDestination(SmsTracker tracker) { 9830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mContext.checkCallingOrSelfPermission(SEND_SMS_NO_CONFIRMATION_PERMISSION) 9840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville == PackageManager.PERMISSION_GRANTED) { 9850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return true; // app is pre-approved to send to short codes 9860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 987ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt int rule = mPremiumSmsRule.get(); 988ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt int smsCategory = SmsUsageMonitor.CATEGORY_NOT_SHORT_CODE; 989ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (rule == PREMIUM_RULE_USE_SIM || rule == PREMIUM_RULE_USE_BOTH) { 990ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt String simCountryIso = mTelephonyManager.getSimCountryIso(); 991ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (simCountryIso == null || simCountryIso.length() != 2) { 992ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get SIM country Iso: trying network country Iso"); 993ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt simCountryIso = mTelephonyManager.getNetworkCountryIso(); 994ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 995ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 996ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt smsCategory = mUsageMonitor.checkDestination(tracker.mDestAddress, simCountryIso); 997ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 998ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (rule == PREMIUM_RULE_USE_NETWORK || rule == PREMIUM_RULE_USE_BOTH) { 999ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt String networkCountryIso = mTelephonyManager.getNetworkCountryIso(); 1000ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (networkCountryIso == null || networkCountryIso.length() != 2) { 1001ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get Network country Iso: trying SIM country Iso"); 1002ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt networkCountryIso = mTelephonyManager.getSimCountryIso(); 1003ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 1004ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 1005cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville smsCategory = SmsUsageMonitor.mergeShortCodeCategories(smsCategory, 1006ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mUsageMonitor.checkDestination(tracker.mDestAddress, networkCountryIso)); 10070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1009ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (smsCategory == SmsUsageMonitor.CATEGORY_NOT_SHORT_CODE 1010ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt || smsCategory == SmsUsageMonitor.CATEGORY_FREE_SHORT_CODE 1011ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt || smsCategory == SmsUsageMonitor.CATEGORY_STANDARD_SHORT_CODE) { 10124658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return true; // not a premium short code 10134658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 10144658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 10154658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // Wait for user confirmation unless the user has set permission to always allow/deny 10164658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int premiumSmsPermission = mUsageMonitor.getPremiumSmsPermission( 10174658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby tracker.mAppInfo.packageName); 10184658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (premiumSmsPermission == SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) { 10194658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // First time trying to send to premium SMS. 10204658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby premiumSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER; 10214658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 10220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10234658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby switch (premiumSmsPermission) { 10244658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW: 1025ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "User approved this app to send to premium SMS"); 10264658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return true; 10270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10284658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW: 1029ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.w(TAG, "User denied this app from sending to premium SMS"); 10304658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby sendMessage(obtainMessage(EVENT_STOP_SENDING, tracker)); 10314658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return false; // reject this message 10324658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 10334658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER: 10340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 10354658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int event; 1036ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (smsCategory == SmsUsageMonitor.CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE) { 10374658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby event = EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE; 10384658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } else { 10394658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby event = EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE; 10404658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 10414658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby sendMessage(obtainMessage(event, tracker)); 10424658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return false; // wait for user confirmation 10430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Deny sending an SMS if the outgoing queue limit is reached. Used when the message 10490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * must be confirmed by the user due to excessive usage or potential premium SMS detected. 10500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker the SmsTracker for the message to send 10510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the message was denied; false to continue with send confirmation 10520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean denyIfQueueLimitReached(SmsTracker tracker) { 10540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mPendingTrackerCount >= MO_MSG_QUEUE_LIMIT) { 10550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Deny sending message when the queue limit is reached. 1056c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Denied because queue limit reached"); 1057c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_LIMIT_EXCEEDED, 0/*errorCode*/); 10580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return true; 10590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPendingTrackerCount++; 10610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return false; 10620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Returns the label for the specified app package name. 10660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param appPackage the package name of the app requesting to send an SMS 10670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return the label for the specified app, or the package name if getApplicationInfo() fails 10680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private CharSequence getAppLabel(String appPackage) { 10700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PackageManager pm = mContext.getPackageManager(); 10710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 10720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ApplicationInfo appInfo = pm.getApplicationInfo(appPackage, 0); 10730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return appInfo.loadLabel(pm); 10740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (PackageManager.NameNotFoundException e) { 1075ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "PackageManager Name Not Found for package " + appPackage); 10760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return appPackage; // fall back to package name if we can't get app label 10770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Post an alert when SMS needs confirmation due to excessive usage. 10820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker an SmsTracker for the current message. 10830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void handleReachSentLimit(SmsTracker tracker) { 10850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (denyIfQueueLimitReached(tracker)) { 10860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; // queue limit reached; error was returned to caller 10870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10892029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra CharSequence appLabel = getAppLabel(tracker.mAppInfo.packageName); 10900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Resources r = Resources.getSystem(); 10910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Spanned messageText = Html.fromHtml(r.getString(R.string.sms_control_message, appLabel)); 10920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 109378df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ConfirmDialogListener listener = new ConfirmDialogListener(tracker, null); 10940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AlertDialog d = new AlertDialog.Builder(mContext) 10960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setTitle(R.string.sms_control_title) 10970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setIcon(R.drawable.stat_sys_warning) 10980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setMessage(messageText) 10990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setPositiveButton(r.getString(R.string.sms_control_yes), listener) 11000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setNegativeButton(r.getString(R.string.sms_control_no), listener) 11010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setOnCancelListener(listener) 11020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .create(); 11030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 11050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.show(); 11060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 11090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Post an alert for user confirmation when sending to a potential short code. 11100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param isPremium true if the destination is known to be a premium short code 11110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker the SmsTracker for the current message. 11120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 11130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void handleConfirmShortCode(boolean isPremium, SmsTracker tracker) { 11140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (denyIfQueueLimitReached(tracker)) { 11150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; // queue limit reached; error was returned to caller 11160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11184658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int detailsId; 11190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (isPremium) { 11204658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby detailsId = R.string.sms_premium_short_code_details; 11210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 11224658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby detailsId = R.string.sms_short_code_details; 11230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11252029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra CharSequence appLabel = getAppLabel(tracker.mAppInfo.packageName); 11260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Resources r = Resources.getSystem(); 11274658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby Spanned messageText = Html.fromHtml(r.getString(R.string.sms_short_code_confirm_message, 11284658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby appLabel, tracker.mDestAddress)); 11290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11304658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 11314658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby Context.LAYOUT_INFLATER_SERVICE); 11324658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby View layout = inflater.inflate(R.layout.sms_short_code_confirmation_dialog, null); 11334658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 113478df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ConfirmDialogListener listener = new ConfirmDialogListener(tracker, 113578df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt (TextView)layout.findViewById(R.id.sms_short_code_remember_undo_instruction)); 113678df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt 113778df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt 11384658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby TextView messageView = (TextView) layout.findViewById(R.id.sms_short_code_confirm_message); 11394658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby messageView.setText(messageText); 11404658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 114178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ViewGroup detailsLayout = (ViewGroup) layout.findViewById( 11424658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby R.id.sms_short_code_detail_layout); 11434658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby TextView detailsView = (TextView) detailsLayout.findViewById( 11444658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby R.id.sms_short_code_detail_message); 11454658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby detailsView.setText(detailsId); 11464658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 11474658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby CheckBox rememberChoice = (CheckBox) layout.findViewById( 11484658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby R.id.sms_short_code_remember_choice_checkbox); 11494658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby rememberChoice.setOnCheckedChangeListener(listener); 11504658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 11510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AlertDialog d = new AlertDialog.Builder(mContext) 11524658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby .setView(layout) 11530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setPositiveButton(r.getString(R.string.sms_short_code_confirm_allow), listener) 11540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setNegativeButton(r.getString(R.string.sms_short_code_confirm_deny), listener) 11550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setOnCancelListener(listener) 11560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .create(); 11570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 11590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.show(); 11604658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 11614658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby listener.setPositiveButton(d.getButton(DialogInterface.BUTTON_POSITIVE)); 11624658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby listener.setNegativeButton(d.getButton(DialogInterface.BUTTON_NEGATIVE)); 11634658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 11644658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 11654658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby /** 11664658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * Returns the premium SMS permission for the specified package. If the package has never 11674658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * been seen before, the default {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER} 11684658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * will be returned. 11694658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @param packageName the name of the package to query permission 11704658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @return one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_UNKNOWN}, 11714658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER}, 11724658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or 11734658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW} 11744658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby */ 11754658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby public int getPremiumSmsPermission(String packageName) { 11764658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return mUsageMonitor.getPremiumSmsPermission(packageName); 11774658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 11784658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 11794658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby /** 11804658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * Sets the premium SMS permission for the specified package and save the value asynchronously 11814658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * to persistent storage. 11824658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @param packageName the name of the package to set permission 11834658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @param permission one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER}, 11844658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or 11854658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW} 11864658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby */ 11874658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby public void setPremiumSmsPermission(String packageName, int permission) { 11884658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mUsageMonitor.setPremiumSmsPermission(packageName, permission); 11890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 11920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send the message along to the radio. 11930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 11940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker holds the SMS message to send 11950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 11960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract void sendSms(SmsTracker tracker); 11970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 11998d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * Send the SMS via the PSTN network. 12008d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * 12018d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * @param tracker holds the Sms tracker ready to be sent 12028d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang */ 12038d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang protected abstract void sendSmsByPstn(SmsTracker tracker); 12048d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 12058d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang /** 12061260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * Retry the message along to the radio. 12071260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * 12081260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * @param tracker holds the SMS message to send 12091260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa */ 1210ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa public void sendRetrySms(SmsTracker tracker) { 1211ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa // re-routing to ImsSMSDispatcher 1212ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa if (mImsSMSDispatcher != null) { 1213ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa mImsSMSDispatcher.sendRetrySms(tracker); 1214ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } else { 1215ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa Rlog.e(TAG, mImsSMSDispatcher + " is null. Retry failed"); 1216ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1217ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 12181260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 12191260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** 12200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send the multi-part SMS based on multipart Sms tracker 12210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 12220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker holds the multipart Sms tracker ready to be sent 12230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 12240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void sendMultipartSms(SmsTracker tracker) { 12250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<String> parts; 12260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<PendingIntent> sentIntents; 12270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<PendingIntent> deliveryIntents; 12280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville HashMap<String, Object> map = tracker.mData; 12300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String destinationAddress = (String) map.get("destination"); 12320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String scAddress = (String) map.get("scaddress"); 12330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville parts = (ArrayList<String>) map.get("parts"); 12350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntents = (ArrayList<PendingIntent>) map.get("sentIntents"); 12360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville deliveryIntents = (ArrayList<PendingIntent>) map.get("deliveryIntents"); 12370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // check if in service 12390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int ss = mPhone.getServiceState().getState(); 12401260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // if sms over IMS is not supported on data and voice is not available... 12411260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) { 12420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0, count = parts.size(); i < count; i++) { 12430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent sentIntent = null; 12440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntents != null && sentIntents.size() > i) { 12450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent = sentIntents.get(i); 12460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleNotInService(ss, sentIntent); 12480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 12500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1252b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen sendMultipartText(destinationAddress, scAddress, parts, sentIntents, deliveryIntents, 1253b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen null/*messageUri*/, null/*callingPkg*/); 12540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 12570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Keeps track of an SMS that has been sent to the RIL, until it has 12580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * successfully been sent, or we're done trying. 12590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 12600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final class SmsTracker { 12610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // fields need to be public for derived SmsDispatchers 12620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final HashMap<String, Object> mData; 12630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int mRetryCount; 12641260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa public int mImsRetry; // nonzero indicates initial message was sent over Ims 12650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int mMessageRef; 12666ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi public boolean mExpectMore; 12671260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String mFormat; 12680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final PendingIntent mSentIntent; 12700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final PendingIntent mDeliveryIntent; 12710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12722029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra public final PackageInfo mAppInfo; 12730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final String mDestAddress; 12740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 127578d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal public final SmsHeader mSmsHeader; 127678d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal 12770217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun private long mTimestamp = System.currentTimeMillis(); 1278c99dab56e20222b28cbc6238645feac938f1c333Ye Wen public Uri mMessageUri; // Uri of persisted message if we wrote one 1279c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1280c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // Reference to states of a multipart message that this part belongs to 1281c99dab56e20222b28cbc6238645feac938f1c333Ye Wen private AtomicInteger mUnsentPartCount; 1282c99dab56e20222b28cbc6238645feac938f1c333Ye Wen private AtomicBoolean mAnyPartFailed; 12834bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // The full message content of a single part message 12844bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // or a multipart message that this part belongs to 12854bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen private String mFullMessageText; 12864bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen 12874bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen private int mSubId; 12880217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 128952a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen // If this is a text message (instead of data message) 129052a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen private boolean mIsText; 129152a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen 12921260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa private SmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, 1293c99dab56e20222b28cbc6238645feac938f1c333Ye Wen PendingIntent deliveryIntent, PackageInfo appInfo, String destAddr, String format, 129478d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, 129552a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen SmsHeader smsHeader, boolean isExpectMore, String fullMessageText, int subId, 129652a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen boolean isText) { 12970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mData = data; 12980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mSentIntent = sentIntent; 12990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mDeliveryIntent = deliveryIntent; 13000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRetryCount = 0; 13012029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra mAppInfo = appInfo; 13020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mDestAddress = destAddr; 13031260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mFormat = format; 13046ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi mExpectMore = isExpectMore; 13051260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mImsRetry = 0; 13061260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mMessageRef = 0; 1307c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mUnsentPartCount = unsentPartCount; 1308c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mAnyPartFailed = anyPartFailed; 1309c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mMessageUri = messageUri; 131078d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal mSmsHeader = smsHeader; 13114bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen mFullMessageText = fullMessageText; 13124bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen mSubId = subId; 131352a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen mIsText = isText; 13140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 13160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 13170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Returns whether this tracker holds a multi-part SMS. 13180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the tracker holds a multi-part SMS; false otherwise 13190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 13200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby boolean isMultipart() { 13210217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun return mData.containsKey("parts"); 13220217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 13230217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 13240217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun /** 13250217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun * Update the status of this message if we persisted it 13260217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun */ 13270217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun public void updateSentMessageStatus(Context context, int status) { 1328c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mMessageUri != null) { 13290217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun // If we wrote this message in writeSentMessage, update it now 13300217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun ContentValues values = new ContentValues(1); 13310217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun values.put(Sms.STATUS, status); 13320217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun SqliteWrapper.update(context, context.getContentResolver(), 1333c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mMessageUri, values, null, null); 1334c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1335c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1336c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1337c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 13384bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * Set the final state of a message: FAILED or SENT 1339c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * 1340c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param context The Context 13414bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param messageType The final message type 1342c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param errorCode The error code 1343c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 13444bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen private void updateMessageState(Context context, int messageType, int errorCode) { 1345c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mMessageUri == null) { 1346c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return; 1347c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 13484bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final ContentValues values = new ContentValues(2); 13494bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.TYPE, messageType); 1350c99dab56e20222b28cbc6238645feac938f1c333Ye Wen values.put(Sms.ERROR_CODE, errorCode); 1351c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final long identity = Binder.clearCallingIdentity(); 1352c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 1353c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (SqliteWrapper.update(context, context.getContentResolver(), mMessageUri, values, 1354c99dab56e20222b28cbc6238645feac938f1c333Ye Wen null/*where*/, null/*selectionArgs*/) != 1) { 13554bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen Rlog.e(TAG, "Failed to move message to " + messageType); 1356c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1357c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } finally { 1358c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Binder.restoreCallingIdentity(identity); 1359c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1360c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1361c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1362c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 136352a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen * Persist a sent SMS if required: 136452a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen * 1. It is a text message 136552a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen * 2. SmsApplication tells us to persist: sent from apps that are not default-SMS app or 136652a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen * bluetooth 1367c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * 13684bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param context 13694bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param messageType The folder to store (FAILED or SENT) 13704bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param errorCode The current error code for this SMS or SMS part 13714bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @return The telephony provider URI if stored 1372c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 13734bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen private Uri persistSentMessageIfRequired(Context context, int messageType, int errorCode) { 137452a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen if (!mIsText || 137552a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen !SmsApplication.shouldWriteMessageForPackage(mAppInfo.packageName, context)) { 13764bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen return null; 13774bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } 13784bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen Rlog.d(TAG, "Persist SMS into " 13794bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen + (messageType == Sms.MESSAGE_TYPE_FAILED ? "FAILED" : "SENT")); 13804bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final ContentValues values = new ContentValues(); 13814b09dff383ae7dfca595aeeea886a594a1947340Wink Saville values.put(Sms.SUBSCRIPTION_ID, mSubId); 13824bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.ADDRESS, mDestAddress); 13834bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.BODY, mFullMessageText); 13844bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.DATE, System.currentTimeMillis()); // milliseconds 13854bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.SEEN, 1); 13864bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.READ, 1); 13874bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final String creator = mAppInfo != null ? mAppInfo.packageName : null; 13884bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen if (!TextUtils.isEmpty(creator)) { 13894bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.CREATOR, creator); 13904bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } 13914bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen if (mDeliveryIntent != null) { 13924bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.STATUS, Telephony.Sms.STATUS_PENDING); 13934bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } 13944bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen if (errorCode != 0) { 13954bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.ERROR_CODE, errorCode); 1396c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1397c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final long identity = Binder.clearCallingIdentity(); 13984bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final ContentResolver resolver = context.getContentResolver(); 1399c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 14004bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final Uri uri = resolver.insert(Telephony.Sms.Sent.CONTENT_URI, values); 14014bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen if (uri != null && messageType == Sms.MESSAGE_TYPE_FAILED) { 14024bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // Since we can't persist a message directly into FAILED box, 14034bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // we have to update the column after we persist it into SENT box. 14044bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // The gap between the state change is tiny so I would not expect 14054bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // it to cause any serious problem 14064bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // TODO: we should add a "failed" URI for this in SmsProvider? 14074bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final ContentValues updateValues = new ContentValues(1); 14084bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen updateValues.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED); 14094bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen resolver.update(uri, updateValues, null/*where*/, null/*selectionArgs*/); 1410c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 14114bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen return uri; 14124bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } catch (Exception e) { 14134bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen Rlog.e(TAG, "writeOutboxMessage: Failed to persist outbox message", e); 14144bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen return null; 1415c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } finally { 1416c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Binder.restoreCallingIdentity(identity); 1417c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1418c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1419c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1420c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 14214bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * Persist or update an SMS depending on if we send a new message or a stored message 14224bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * 14234bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param context 14244bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param messageType The message folder for this SMS, FAILED or SENT 14254bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param errorCode The current error code for this SMS or SMS part 14264bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen */ 14274bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen private void persistOrUpdateMessage(Context context, int messageType, int errorCode) { 14284bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen if (mMessageUri != null) { 14294bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen updateMessageState(context, messageType, errorCode); 14304bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } else { 14314bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen mMessageUri = persistSentMessageIfRequired(context, messageType, errorCode); 14324bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } 14334bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } 14344bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen 14354bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen /** 1436c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * Handle a failure of a single part message or a part of a multipart message 1437c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * 1438c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param context The Context 1439c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param error The error to send back with 1440c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param errorCode 1441c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 1442c99dab56e20222b28cbc6238645feac938f1c333Ye Wen public void onFailed(Context context, int error, int errorCode) { 1443c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mAnyPartFailed != null) { 1444c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mAnyPartFailed.set(true); 1445c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1446c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // is single part or last part of multipart message 1447c99dab56e20222b28cbc6238645feac938f1c333Ye Wen boolean isSinglePartOrLastPart = true; 1448c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mUnsentPartCount != null) { 1449c99dab56e20222b28cbc6238645feac938f1c333Ye Wen isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0; 1450c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1451c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (isSinglePartOrLastPart) { 14524bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen persistOrUpdateMessage(context, Sms.MESSAGE_TYPE_FAILED, errorCode); 1453c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1454c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mSentIntent != null) { 1455c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 1456fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen // Extra information to send with the sent intent 1457fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen Intent fillIn = new Intent(); 1458fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen if (mMessageUri != null) { 1459fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen // Pass this to SMS apps so that they know where it is stored 1460fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen fillIn.putExtra("uri", mMessageUri.toString()); 1461fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen } 1462c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (errorCode != 0) { 1463c99dab56e20222b28cbc6238645feac938f1c333Ye Wen fillIn.putExtra("errorCode", errorCode); 1464c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1465c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mUnsentPartCount != null && isSinglePartOrLastPart) { 1466c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // Is multipart and last part 1467c99dab56e20222b28cbc6238645feac938f1c333Ye Wen fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true); 1468c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1469c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mSentIntent.send(context, error, fillIn); 1470c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } catch (CanceledException ex) { 1471c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Failed to send result"); 1472c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1473c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1474c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1475c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1476c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 1477c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * Handle the sent of a single part message or a part of a multipart message 1478c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * 1479c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param context The Context 1480c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 1481c99dab56e20222b28cbc6238645feac938f1c333Ye Wen public void onSent(Context context) { 1482c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // is single part or last part of multipart message 1483c99dab56e20222b28cbc6238645feac938f1c333Ye Wen boolean isSinglePartOrLastPart = true; 1484c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mUnsentPartCount != null) { 1485c99dab56e20222b28cbc6238645feac938f1c333Ye Wen isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0; 1486c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1487c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (isSinglePartOrLastPart) { 14884bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen int messageType = Sms.MESSAGE_TYPE_SENT; 1489c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mAnyPartFailed != null && mAnyPartFailed.get()) { 14904bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen messageType = Sms.MESSAGE_TYPE_FAILED; 1491c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 14924bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen persistOrUpdateMessage(context, messageType, 0/*errorCode*/); 1493c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1494c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mSentIntent != null) { 1495c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 1496fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen // Extra information to send with the sent intent 1497fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen Intent fillIn = new Intent(); 1498fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen if (mMessageUri != null) { 1499fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen // Pass this to SMS apps so that they know where it is stored 1500fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen fillIn.putExtra("uri", mMessageUri.toString()); 1501fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen } 1502c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mUnsentPartCount != null && isSinglePartOrLastPart) { 1503c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // Is multipart and last part 1504fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true); 1505c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1506fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen mSentIntent.send(context, Activity.RESULT_OK, fillIn); 1507c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } catch (CanceledException ex) { 1508c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Failed to send result"); 1509c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 15100217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 15110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1514ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected SmsTracker getSmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, 1515c99dab56e20222b28cbc6238645feac938f1c333Ye Wen PendingIntent deliveryIntent, String format, AtomicInteger unsentPartCount, 15166ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi AtomicBoolean anyPartFailed, Uri messageUri, SmsHeader smsHeader, 151752a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen boolean isExpectMore, String fullMessageText, boolean isText) { 15181260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Get calling app package name via UID from Binder call 15191260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa PackageManager pm = mContext.getPackageManager(); 15201260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String[] packageNames = pm.getPackagesForUid(Binder.getCallingUid()); 15211260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 15221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Get package info via packagemanager 15231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa PackageInfo appInfo = null; 15241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (packageNames != null && packageNames.length > 0) { 15251260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa try { 15261260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // XXX this is lossy- apps can share a UID 15271260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa appInfo = pm.getPackageInfo(packageNames[0], PackageManager.GET_SIGNATURES); 15281260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } catch (PackageManager.NameNotFoundException e) { 15291260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // error will be logged in sendRawPdu 15301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 15311260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 15321260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Strip non-digits from destination phone number before checking for short codes 15331260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // and before displaying the number to the user if confirmation is required. 15341260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String destAddr = PhoneNumberUtils.extractNetworkPortion((String) data.get("destAddr")); 1535c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return new SmsTracker(data, sentIntent, deliveryIntent, appInfo, destAddr, format, 15364bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen unsentPartCount, anyPartFailed, messageUri, smsHeader, isExpectMore, 153752a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen fullMessageText, getSubId(), isText); 1538c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1539c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1540c99dab56e20222b28cbc6238645feac938f1c333Ye Wen protected SmsTracker getSmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, 15414bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen PendingIntent deliveryIntent, String format, Uri messageUri, boolean isExpectMore, 154252a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen String fullMessageText, boolean isText) { 1543c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return getSmsTracker(data, sentIntent, deliveryIntent, format, null/*unsentPartCount*/, 15444bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen null/*anyPartFailed*/, messageUri, null/*smsHeader*/, isExpectMore, 154552a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen fullMessageText, isText); 15461260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 15471260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1548ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr, 15491260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String text, SmsMessageBase.SubmitPduBase pdu) { 15501260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa HashMap<String, Object> map = new HashMap<String, Object>(); 15511260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("destAddr", destAddr); 15521260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("scAddr", scAddr); 15531260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("text", text); 15541260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("smsc", pdu.encodedScAddress); 15551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("pdu", pdu.encodedMessage); 15561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa return map; 15571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 15581260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1559ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr, 15601260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu) { 15611260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa HashMap<String, Object> map = new HashMap<String, Object>(); 15621260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("destAddr", destAddr); 15631260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("scAddr", scAddr); 1564ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa map.put("destPort", destPort); 15651260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("data", data); 15661260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("smsc", pdu.encodedScAddress); 15671260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("pdu", pdu.encodedMessage); 15681260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa return map; 15691260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 15701260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 15710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 15720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Dialog listener for SMS confirmation dialog. 15730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 15740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final class ConfirmDialogListener 15754658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, 15764658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby CompoundButton.OnCheckedChangeListener { 15770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 15780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final SmsTracker mTracker; 15794658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby private Button mPositiveButton; 15804658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby private Button mNegativeButton; 15814658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby private boolean mRememberChoice; // default is unchecked 158278df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt private final TextView mRememberUndoInstruction; 15830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 158478df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ConfirmDialogListener(SmsTracker tracker, TextView textView) { 15850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mTracker = tracker; 158678df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction = textView; 15870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 15894658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby void setPositiveButton(Button button) { 15904658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mPositiveButton = button; 15914658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 15924658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 15934658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby void setNegativeButton(Button button) { 15944658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mNegativeButton = button; 15954658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 15964658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 15970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 15980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void onClick(DialogInterface dialog, int which) { 15994658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // Always set the SMS permission so that Settings will show a permission setting 16004658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // for the app (it won't be shown until after the app tries to send to a short code). 16014658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER; 16024658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 16030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (which == DialogInterface.BUTTON_POSITIVE) { 1604ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "CONFIRM sending SMS"); 16052029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // XXX this is lossy- apps can have more than one signature 1606634a24f56f54b5d2911649288147c750b67c7ae4William Luh EventLog.writeEvent(EventLogTags.EXP_DET_SMS_SENT_BY_USER, 1607ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh mTracker.mAppInfo.applicationInfo == null ? 1608ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh -1 : mTracker.mAppInfo.applicationInfo.uid); 16090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_SEND_CONFIRMED_SMS, mTracker)); 16104658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (mRememberChoice) { 16114658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW; 16124658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 16130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (which == DialogInterface.BUTTON_NEGATIVE) { 1614ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "DENY sending SMS"); 16152029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // XXX this is lossy- apps can have more than one signature 1616634a24f56f54b5d2911649288147c750b67c7ae4William Luh EventLog.writeEvent(EventLogTags.EXP_DET_SMS_DENIED_BY_USER, 1617ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh mTracker.mAppInfo.applicationInfo == null ? 1618ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh -1 : mTracker.mAppInfo.applicationInfo.uid); 16190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_STOP_SENDING, mTracker)); 16204658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (mRememberChoice) { 16214658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW; 16224658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 16230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16244658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby setPremiumSmsPermission(mTracker.mAppInfo.packageName, newSmsPermission); 16250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 16280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void onCancel(DialogInterface dialog) { 1629ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "dialog dismissed: don't send SMS"); 16300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_STOP_SENDING, mTracker)); 16310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16324658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 16334658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby @Override 16344658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1635ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "remember this choice: " + isChecked); 16364658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mRememberChoice = isChecked; 16374658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (isChecked) { 16384658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mPositiveButton.setText(R.string.sms_short_code_confirm_always_allow); 16394658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mNegativeButton.setText(R.string.sms_short_code_confirm_never_allow); 164078df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt if (mRememberUndoInstruction != null) { 164178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction. 164278df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt setText(R.string.sms_short_code_remember_undo_instruction); 164378df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction.setPadding(0,0,0,32); 164478df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt } 16454658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } else { 16464658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mPositiveButton.setText(R.string.sms_short_code_confirm_allow); 16475d875796122cdd8a7004e8e3964b20b5c65a31a1Robert Greenwalt mNegativeButton.setText(R.string.sms_short_code_confirm_deny); 164878df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt if (mRememberUndoInstruction != null) { 164978df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction.setText(""); 165078df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction.setPadding(0,0,0,0); 165178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt } 16524658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 16534658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 16540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1656ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa public boolean isIms() { 1657ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa if (mImsSMSDispatcher != null) { 1658ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return mImsSMSDispatcher.isIms(); 1659ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } else { 1660ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa Rlog.e(TAG, mImsSMSDispatcher + " is null"); 1661ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return false; 1662ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1663ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 16641260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1665ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa public String getImsSmsFormat() { 1666ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa if (mImsSMSDispatcher != null) { 1667ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return mImsSMSDispatcher.getImsSmsFormat(); 1668ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } else { 1669ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa Rlog.e(TAG, mImsSMSDispatcher + " is null"); 1670ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return null; 1671ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1672ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1673c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1674c99dab56e20222b28cbc6238645feac938f1c333Ye Wen private String getMultipartMessageText(ArrayList<String> parts) { 1675c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final StringBuilder sb = new StringBuilder(); 1676c99dab56e20222b28cbc6238645feac938f1c333Ye Wen for (String part : parts) { 1677c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (part != null) { 1678c99dab56e20222b28cbc6238645feac938f1c333Ye Wen sb.append(part); 1679c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1680c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1681c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return sb.toString(); 1682c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1683b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen 16848215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected String getCarrierAppPackageName() { 1685062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId()); 16867f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal if (card == null) { 16877f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal return null; 16887f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal } 16897f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal 1690934a24a6aa2b7a981e872fa350648904ed80280aDiego Pontoriero List<String> carrierPackages = card.getCarrierPackageNamesForIntent( 16918215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mContext.getPackageManager(), new Intent(CarrierMessagingService.SERVICE_INTERFACE)); 16927f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal return (carrierPackages != null && carrierPackages.size() == 1) ? 16937f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal carrierPackages.get(0) : null; 1694c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal } 1695c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal 1696b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville protected int getSubId() { 1697b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen return SubscriptionController.getInstance().getSubIdUsingPhoneId(mPhone.mPhoneId); 1698b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 16990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville} 1700