SMSDispatcher.java revision b237a11044ed842d2865ff8c8716befb06b6ca25
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; 228d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport android.content.BroadcastReceiver; 230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.ContentResolver; 240217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.content.ContentValues; 250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Context; 260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.DialogInterface; 270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Intent; 280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.ApplicationInfo; 292029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condraimport android.content.pm.PackageInfo; 300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.PackageManager; 310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.res.Resources; 32ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwaltimport android.database.ContentObserver; 330217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.database.sqlite.SqliteWrapper; 340217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.net.Uri; 350825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult; 360825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Binder; 378d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport android.os.Bundle; 380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler; 390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message; 400825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.SystemProperties; 41ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwaltimport android.provider.Settings; 420217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.provider.Telephony; 430217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.provider.Telephony.Sms; 448d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport android.provider.Telephony.Sms.Intents; 450825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.PhoneNumberUtils; 460d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.Rlog; 470825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.ServiceState; 48f1aeeb51f2c62420012122e0ccc75b3940c570e4Ye Wenimport android.telephony.SmsManager; 490825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.TelephonyManager; 500825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.Html; 510825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.Spanned; 52b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.text.TextUtils; 532029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condraimport android.util.EventLog; 544658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.view.LayoutInflater; 554658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.view.View; 5678df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwaltimport android.view.ViewGroup; 570825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.WindowManager; 584658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.Button; 594658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.CheckBox; 604658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.CompoundButton; 614658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.TextView; 620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 630825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.R; 640825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; 65a9552aa6bf3ce12c75ad43165034d9a1233fb131Shishir Agrawalimport com.android.internal.telephony.uicc.UiccCard; 66c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport com.android.internal.telephony.uicc.UiccController; 670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 680825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList; 698d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport java.util.Collections; 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); 1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mSmsSendDisabled = !SystemProperties.getBoolean( 1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TelephonyProperties.PROPERTY_SMS_SEND, 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 2658d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang /** Outgoing messages being handled by the carrier app. */ 2668d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang protected final List<SmsTracker> sendPendingList = 2678d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Collections.synchronizedList(new ArrayList<SmsTracker>()); 2688d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Handles events coming from the phone stack. Overridden from handler. 2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param msg the message to handle 2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void handleMessage(Message msg) { 2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (msg.what) { 2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_SMS_COMPLETE: 2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // An outbound SMS has been successfully transferred, or failed. 2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleSendComplete((AsyncResult) msg.obj); 2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_RETRY: 2831260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa Rlog.d(TAG, "SMS retry.."); 2841260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa sendRetrySms((SmsTracker) msg.obj); 2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_LIMIT_REACHED_CONFIRMATION: 2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleReachSentLimit((SmsTracker)(msg.obj)); 2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE: 2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleConfirmShortCode(false, (SmsTracker)(msg.obj)); 2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE: 2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleConfirmShortCode(true, (SmsTracker)(msg.obj)); 2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_CONFIRMED_SMS: 3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsTracker tracker = (SmsTracker) msg.obj; 3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (tracker.isMultipart()) { 3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMultipartSms(tracker); 3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 3056c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying if (mPendingTrackerCount > 1) { 3066c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying tracker.mExpectMore = true; 3076c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying } else { 3086c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying tracker.mExpectMore = false; 3096c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying } 3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendSms(tracker); 3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPendingTrackerCount--; 3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_STOP_SENDING: 3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsTracker tracker = (SmsTracker) msg.obj; 319c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_LIMIT_EXCEEDED, 0/*errorCode*/); 3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPendingTrackerCount--; 3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3240d4bcdf379842af4b6304809156971e926f374f0Jake Hamby case EVENT_HANDLE_STATUS_REPORT: 3250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby handleStatusReport(msg.obj); 3260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby break; 3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby default: 3290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.e(TAG, "handleMessage() ignoring message of unexpected type " + msg.what); 3300d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 331b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby } 332b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby 333b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby /** 3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Called when SMS send completes. Broadcasts a sentIntent on success. 3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * On failure, either sets up retries or broadcasts a sentIntent with 3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the failure in the result code. 3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param ar AsyncResult passed into the message handler. ar.result should 3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * an SmsResponse instance if send was successful. ar.userObj 3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * should be an SmsTracker instance. 3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void handleSendComplete(AsyncResult ar) { 3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsTracker tracker = (SmsTracker) ar.userObj; 3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent sentIntent = tracker.mSentIntent; 3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 346454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks if (ar.result != null) { 3475a176f73dbb2bff2ca8b8f86af86a17be6863b87Wink Saville tracker.mMessageRef = ((SmsResponse)ar.result).mMessageRef; 348454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks } else { 349454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks Rlog.d(TAG, "SmsResponse was null"); 350454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks } 351454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks 3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.exception == null) { 353cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville if (DBG) Rlog.d(TAG, "SMS send complete. Broadcasting intent: " + sentIntent); 3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (tracker.mDeliveryIntent != null) { 3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Expecting a status report. Add it to the list. 3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville deliveryPendingList.add(tracker); 3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 359c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onSent(mContext); 3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 361cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville if (DBG) Rlog.d(TAG, "SMS send failed"); 3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int ss = mPhone.getServiceState().getState(); 3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3651260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if ( tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) { 3661260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // This is retry after failure over IMS but voice is not available. 3671260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Set retry to max allowed, so no retry is sent and 3681260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // cause RESULT_ERROR_GENERIC_FAILURE to be returned to app. 3691260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa tracker.mRetryCount = MAX_SEND_RETRIES; 3701260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 3711260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa Rlog.d(TAG, "handleSendComplete: Skipping retry: " 3721260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" isIms()="+isIms() 3731260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" mRetryCount="+tracker.mRetryCount 3741260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" mImsRetry="+tracker.mImsRetry 3751260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" mMessageRef="+tracker.mMessageRef 3761260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" SS= "+mPhone.getServiceState().getState()); 3771260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 3781260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 3791260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // if sms over IMS is not supported on data and voice is not available... 3801260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) { 381c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, getNotInServiceError(ss), 0/*errorCode*/); 3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if ((((CommandException)(ar.exception)).getCommandError() 3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville == CommandException.Error.SMS_FAIL_RETRY) && 3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tracker.mRetryCount < MAX_SEND_RETRIES) { 3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Retry after a delay if needed. 3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TODO: According to TS 23.040, 9.2.3.6, we should resend 3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // with the same TP-MR as the failed message, and 3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TP-RD set to 1. However, we don't have a means of 3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // knowing the MR for the failed message (EF_SMSstatus 3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // may or may not have the MR corresponding to this 3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // message, depending on the failure). Also, in some 3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // implementations this retry is handled by the baseband. 3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tracker.mRetryCount++; 3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker); 3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessageDelayed(retryMsg, SEND_RETRY_DELAY); 396c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } else { 397c99dab56e20222b28cbc6238645feac938f1c333Ye Wen int errorCode = 0; 398c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (ar.result != null) { 399c99dab56e20222b28cbc6238645feac938f1c333Ye Wen errorCode = ((SmsResponse)ar.result).mErrorCode; 400c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int error = RESULT_ERROR_GENERIC_FAILURE; 4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (((CommandException)(ar.exception)).getCommandError() 4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville == CommandException.Error.FDN_CHECK_FAILURE) { 4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville error = RESULT_ERROR_FDN_CHECK_FAILURE; 4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 406c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, error, errorCode); 4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Handles outbound message when the phone is not in service. 4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param ss Current service state. Valid values are: 4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * OUT_OF_SERVICE 4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * EMERGENCY_ONLY 4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * POWER_OFF 4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntent the PendingIntent to send the error to 4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static void handleNotInService(int ss, PendingIntent sentIntent) { 4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntent != null) { 4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ss == ServiceState.STATE_POWER_OFF) { 4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(RESULT_ERROR_RADIO_OFF); 4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(RESULT_ERROR_NO_SERVICE); 4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CanceledException ex) {} 4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 433c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param ss service state 434c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @return The result error based on input service state for not in service error 435c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 436c99dab56e20222b28cbc6238645feac938f1c333Ye Wen protected static int getNotInServiceError(int ss) { 437c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (ss == ServiceState.STATE_POWER_OFF) { 438c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return RESULT_ERROR_RADIO_OFF; 439c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 440c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return RESULT_ERROR_NO_SERVICE; 441c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 442c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 443c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a data based SMS to a specific application port. 4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param destAddr the address to send the message to 4470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddr is the service center address or null to use 4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the current default SMSC 4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param destPort the port to deliver the message to 4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param data the body of the message to send 4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntent if not NULL this <code>PendingIntent</code> is 4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is successfully sent, or failed. 4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors:<br> 4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code><br> 4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code><br> 4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code><br>. 4590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 4600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the extra "errorCode" containing a radio technology specific value, 4610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * generally only useful for troubleshooting.<br> 4620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 4630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 4650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is delivered to the recipient. The 4670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * raw pdu of the status report is in the extended data ("pdu"). 4680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 4690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract void sendData(String destAddr, String scAddr, int destPort, 4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent); 4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 4730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a text based SMS. 474b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param destAddr the address to send the message to 4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddr is the service center address or null to use 4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the current default SMSC 4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param text the body of the message to send 4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntent if not NULL this <code>PendingIntent</code> is 4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is successfully sent, or failed. 4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors:<br> 4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 4830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code><br> 4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code><br> 4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code><br>. 4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the extra "errorCode" containing a radio technology specific value, 4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * generally only useful for troubleshooting.<br> 4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is delivered to the recipient. The 494b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param messageUri optional URI of the message if it is already stored in the system 495b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param callingPkg the calling package name 4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 497b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen protected abstract void sendText(String destAddr, String scAddr, String text, 498b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri, 499b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen String callingPkg); 5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 50263418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * Inject an SMS PDU into the android platform. 50363418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * 50463418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * @param pdu is the byte array of pdu to be injected into android telephony layer 50563418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * @param format is the format of SMS pdu (3gpp or 3gpp2) 50663418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * @param receivedIntent if not NULL this <code>PendingIntent</code> is 50763418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * broadcast when the message is successfully received by the 50863418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * android telephony layer. This intent is broadcasted at 50963418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * the same time an SMS received from radio is responded back. 51063418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni */ 51163418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni protected abstract void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent); 51263418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni 51363418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni /** 5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Calculate the number of septets needed to encode the message. 5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param messageBody the message to encode 5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param use7bitOnly ignore (but still count) illegal characters if true 5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return TextEncodingDetails 5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract TextEncodingDetails calculateLength(CharSequence messageBody, 5210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean use7bitOnly); 5220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 5248d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * Update the status of a pending (send-by-IP) SMS message and resend by PSTN if necessary. 5258d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * This outbound message was handled by the carrier app. If the carrier app fails to send 5268d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * this message, it would be resent by PSTN. 5278d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * 5288d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * @param messageRef the reference number of the SMS message. 5298d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * @param success True if and only if the message was sent successfully. If its value is 5308d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * false, this message should be resent via PSTN. 5318d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang */ 5328d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang protected abstract void updateSmsSendStatus(int messageRef, boolean success); 5338d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 5348d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang /** 5358d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * Handler for a {@link GsmSMSDispatcher} or {@link CdmaSMSDispatcher} broadcast. 5368d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * If SMS sending is successfuly, sends EVENT_SEND_SMS_COMPLETE message. Otherwise, 5378d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * send the message via the GSM/CDMA network. 5388d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang */ 5398d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang protected final class SMSDispatcherReceiver extends BroadcastReceiver { 5408d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 5418d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang private final SmsTracker mTracker; 5428d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 5438d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang public SMSDispatcherReceiver(SmsTracker tracker) { 5448d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang mTracker = tracker; 5458d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } 5468d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 5478d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang @Override 5488d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang public void onReceive(Context context, Intent intent) { 5498d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang String action = intent.getAction(); 5508d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang if (action.equals(Intents.SMS_SEND_ACTION)) { 5518d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang int rc = getResultCode(); 5528d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang if (rc == Activity.RESULT_OK) { 5538d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Rlog.d(TAG, "Sending SMS by IP pending."); 5548d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Bundle resultExtras = getResultExtras(false); 5558d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang if (resultExtras != null && resultExtras.containsKey("messageref")) { 5568d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang mTracker.mMessageRef = resultExtras.getInt("messageref"); 5578d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Rlog.d(TAG, "messageref = " + mTracker.mMessageRef); 5588d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } else { 5598d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Rlog.e(TAG, "Can't find messageref in result extras."); 5608d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } 5618d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang sendPendingList.add(mTracker); 5628d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } else { 5638d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Rlog.d(TAG, "Sending SMS by IP failed."); 5648d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang sendSmsByPstn(mTracker); 5658d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } 5668d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } else { 5678d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Rlog.e(TAG, "unexpected BroadcastReceiver action: " + action); 5688d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } 5698d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } 5708d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } 5718d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 5728d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang /** 5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a multi-part text based SMS. 574b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param destAddr the address to send the message to 5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddr is the service center address or null to use 5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the current default SMSC 5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param parts an <code>ArrayList</code> of strings that, in order, 5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * comprise the original message 5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntents if not null, an <code>ArrayList</code> of 5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>PendingIntent</code>s (one for each message part) that is 5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the corresponding message part has been sent. 5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors: 5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code> 5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code> 5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code> 5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code>. 5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param deliveryIntents if not null, an <code>ArrayList</code> of 5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>PendingIntent</code>s (one for each message part) that is 5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the corresponding message part has been delivered 5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * to the recipient. The raw pdu of the status report is in the 595b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param messageUri optional URI of the message if it is already stored in the system 596b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param callingPkg the calling package name 5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void sendMultipartText(String destAddr, String scAddr, 5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, 600b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg) { 601b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (messageUri == null) { 602f1aeeb51f2c62420012122e0ccc75b3940c570e4Ye Wen if (SmsApplication.shouldWriteMessageForPackage(callingPkg, mContext)) { 603f1aeeb51f2c62420012122e0ccc75b3940c570e4Ye Wen messageUri = writeOutboxMessage( 604f1aeeb51f2c62420012122e0ccc75b3940c570e4Ye Wen getSubId(), 605f1aeeb51f2c62420012122e0ccc75b3940c570e4Ye Wen destAddr, 606f1aeeb51f2c62420012122e0ccc75b3940c570e4Ye Wen getMultipartMessageText(parts), 607f1aeeb51f2c62420012122e0ccc75b3940c570e4Ye Wen deliveryIntents != null && deliveryIntents.size() > 0, 608f1aeeb51f2c62420012122e0ccc75b3940c570e4Ye Wen callingPkg); 609f1aeeb51f2c62420012122e0ccc75b3940c570e4Ye Wen } 610b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } else { 611b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen moveToOutbox(getSubId(), messageUri, callingPkg); 612b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int refNumber = getNextConcatenatedRef() & 0x00FF; 6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int msgCount = parts.size(); 6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int encoding = SmsConstants.ENCODING_UNKNOWN; 6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount]; 6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < msgCount; i++) { 6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TextEncodingDetails details = calculateLength(parts.get(i), false); 6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (encoding != details.codeUnitSize 6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville && (encoding == SmsConstants.ENCODING_UNKNOWN 6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville || encoding == SmsConstants.ENCODING_7BIT)) { 6230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encoding = details.codeUnitSize; 6240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodingForParts[i] = details; 6260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 628c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // States to track at the message level (for all parts) 629c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final AtomicInteger unsentPartCount = new AtomicInteger(msgCount); 630c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final AtomicBoolean anyPartFailed = new AtomicBoolean(false); 631c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 6320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < msgCount; i++) { 6330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); 6340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.refNumber = refNumber; 6350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.seqNumber = i + 1; // 1-based sequence 6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.msgCount = msgCount; 6370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TODO: We currently set this to true since our messaging app will never 6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // send more than 255 parts (it converts the message to MMS well before that). 6390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // However, we should support 3rd party messaging apps that might need 16-bit 6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // references 6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Note: It's not sufficient to just flip this bit to true; it will have 6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // ripple effects (several calculations assume 8-bit ref). 6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.isEightBits = true; 6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsHeader smsHeader = new SmsHeader(); 6450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsHeader.concatRef = concatRef; 6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Set the national language tables for 3GPP 7-bit encoding, if enabled. 6480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (encoding == SmsConstants.ENCODING_7BIT) { 6490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsHeader.languageTable = encodingForParts[i].languageTable; 6500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable; 6510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent sentIntent = null; 6540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntents != null && sentIntents.size() > i) { 6550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent = sentIntents.get(i); 6560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent deliveryIntent = null; 6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (deliveryIntents != null && deliveryIntents.size() > i) { 6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville deliveryIntent = deliveryIntents.get(i); 6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendNewSubmitPdu(destAddr, scAddr, parts.get(i), smsHeader, encoding, 664c99dab56e20222b28cbc6238645feac938f1c333Ye Wen sentIntent, deliveryIntent, (i == (msgCount - 1)), 665c99dab56e20222b28cbc6238645feac938f1c333Ye Wen unsentPartCount, anyPartFailed, messageUri); 6660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 6700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Create a new SubmitPdu and send it. 6710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 6720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract void sendNewSubmitPdu(String destinationAddress, String scAddress, 6730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String message, SmsHeader smsHeader, int encoding, 674c99dab56e20222b28cbc6238645feac938f1c333Ye Wen PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart, 675c99dab56e20222b28cbc6238645feac938f1c333Ye Wen AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri); 6760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 6780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a SMS 6791260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * @param tracker will contain: 6801260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -smsc the SMSC to send the message through, or NULL for the 6810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * default SMSC 6821260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -pdu the raw PDU to send 6831260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -sentIntent if not NULL this <code>Intent</code> is 6840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is successfully sent, or failed. 6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 6860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors: 6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code> 6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code> 6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code> 6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code>. 6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 6930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 6941260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -deliveryIntent if not NULL this <code>Intent</code> is 6950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is delivered to the recipient. The 6960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * raw pdu of the status report is in the extended data ("pdu"). 6971260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -param destAddr the destination phone number (for short code confirmation) 6980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 6991260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected void sendRawPdu(SmsTracker tracker) { 7001260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa HashMap map = tracker.mData; 7011260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa byte pdu[] = (byte[]) map.get("pdu"); 7021260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mSmsSendDisabled) { 704c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Device does not support sending sms."); 705c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_NO_SERVICE, 0/*errorCode*/); 7060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 7070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (pdu == null) { 710c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Empty PDU"); 711c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_NULL_PDU, 0/*errorCode*/); 7120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 7130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Get calling app package name via UID from Binder call 7160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PackageManager pm = mContext.getPackageManager(); 7170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String[] packageNames = pm.getPackagesForUid(Binder.getCallingUid()); 7180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (packageNames == null || packageNames.length == 0) { 7200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Refuse to send SMS if we can't get the calling package name. 721ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get calling app package name: refusing to send SMS"); 722c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/); 7230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 7240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7262029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // Get package info via packagemanager 7270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby PackageInfo appInfo; 7282029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra try { 7292029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // XXX this is lossy- apps can share a UID 7302029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra appInfo = pm.getPackageInfo(packageNames[0], PackageManager.GET_SIGNATURES); 7312029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra } catch (PackageManager.NameNotFoundException e) { 732ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get calling app package info: refusing to send SMS"); 733c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/); 7342029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra return; 7352029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra } 7360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // checkDestination() returns true if the destination is not a premium short code or the 7380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // sending app is approved to send to short codes. Otherwise, a message is sent to our 7390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // handler with the SmsTracker to request user confirmation before sending. 7400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (checkDestination(tracker)) { 7410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // check for excessive outgoing SMS usage by this app 7422029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra if (!mUsageMonitor.check(appInfo.packageName, SINGLE_PART_SMS)) { 7430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, tracker)); 7440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 7450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 747a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal sendSms(tracker); 7480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 7520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Check if destination is a potential premium short code and sender is not pre-approved to 7530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * send to short codes. 7540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 7550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker the tracker for the SMS to send 7560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the destination is approved; false if user confirmation event was sent 7570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 7580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean checkDestination(SmsTracker tracker) { 7590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mContext.checkCallingOrSelfPermission(SEND_SMS_NO_CONFIRMATION_PERMISSION) 7600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville == PackageManager.PERMISSION_GRANTED) { 7610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return true; // app is pre-approved to send to short codes 7620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 763ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt int rule = mPremiumSmsRule.get(); 764ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt int smsCategory = SmsUsageMonitor.CATEGORY_NOT_SHORT_CODE; 765ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (rule == PREMIUM_RULE_USE_SIM || rule == PREMIUM_RULE_USE_BOTH) { 766ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt String simCountryIso = mTelephonyManager.getSimCountryIso(); 767ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (simCountryIso == null || simCountryIso.length() != 2) { 768ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get SIM country Iso: trying network country Iso"); 769ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt simCountryIso = mTelephonyManager.getNetworkCountryIso(); 770ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 771ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 772ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt smsCategory = mUsageMonitor.checkDestination(tracker.mDestAddress, simCountryIso); 773ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 774ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (rule == PREMIUM_RULE_USE_NETWORK || rule == PREMIUM_RULE_USE_BOTH) { 775ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt String networkCountryIso = mTelephonyManager.getNetworkCountryIso(); 776ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (networkCountryIso == null || networkCountryIso.length() != 2) { 777ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get Network country Iso: trying SIM country Iso"); 778ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt networkCountryIso = mTelephonyManager.getSimCountryIso(); 779ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 780ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 781cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville smsCategory = SmsUsageMonitor.mergeShortCodeCategories(smsCategory, 782ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mUsageMonitor.checkDestination(tracker.mDestAddress, networkCountryIso)); 7830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 785ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (smsCategory == SmsUsageMonitor.CATEGORY_NOT_SHORT_CODE 786ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt || smsCategory == SmsUsageMonitor.CATEGORY_FREE_SHORT_CODE 787ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt || smsCategory == SmsUsageMonitor.CATEGORY_STANDARD_SHORT_CODE) { 7884658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return true; // not a premium short code 7894658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 7904658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 7914658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // Wait for user confirmation unless the user has set permission to always allow/deny 7924658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int premiumSmsPermission = mUsageMonitor.getPremiumSmsPermission( 7934658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby tracker.mAppInfo.packageName); 7944658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (premiumSmsPermission == SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) { 7954658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // First time trying to send to premium SMS. 7964658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby premiumSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER; 7974658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 7980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7994658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby switch (premiumSmsPermission) { 8004658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW: 801ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "User approved this app to send to premium SMS"); 8024658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return true; 8030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8044658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW: 805ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.w(TAG, "User denied this app from sending to premium SMS"); 8064658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby sendMessage(obtainMessage(EVENT_STOP_SENDING, tracker)); 8074658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return false; // reject this message 8084658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 8094658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER: 8100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 8114658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int event; 812ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (smsCategory == SmsUsageMonitor.CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE) { 8134658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby event = EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE; 8144658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } else { 8154658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby event = EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE; 8164658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 8174658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby sendMessage(obtainMessage(event, tracker)); 8184658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return false; // wait for user confirmation 8190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Deny sending an SMS if the outgoing queue limit is reached. Used when the message 8250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * must be confirmed by the user due to excessive usage or potential premium SMS detected. 8260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker the SmsTracker for the message to send 8270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the message was denied; false to continue with send confirmation 8280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean denyIfQueueLimitReached(SmsTracker tracker) { 8300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mPendingTrackerCount >= MO_MSG_QUEUE_LIMIT) { 8310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Deny sending message when the queue limit is reached. 832c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Denied because queue limit reached"); 833c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_LIMIT_EXCEEDED, 0/*errorCode*/); 8340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return true; 8350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPendingTrackerCount++; 8370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return false; 8380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Returns the label for the specified app package name. 8420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param appPackage the package name of the app requesting to send an SMS 8430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return the label for the specified app, or the package name if getApplicationInfo() fails 8440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private CharSequence getAppLabel(String appPackage) { 8460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PackageManager pm = mContext.getPackageManager(); 8470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 8480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ApplicationInfo appInfo = pm.getApplicationInfo(appPackage, 0); 8490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return appInfo.loadLabel(pm); 8500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (PackageManager.NameNotFoundException e) { 851ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "PackageManager Name Not Found for package " + appPackage); 8520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return appPackage; // fall back to package name if we can't get app label 8530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Post an alert when SMS needs confirmation due to excessive usage. 8580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker an SmsTracker for the current message. 8590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void handleReachSentLimit(SmsTracker tracker) { 8610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (denyIfQueueLimitReached(tracker)) { 8620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; // queue limit reached; error was returned to caller 8630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8652029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra CharSequence appLabel = getAppLabel(tracker.mAppInfo.packageName); 8660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Resources r = Resources.getSystem(); 8670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Spanned messageText = Html.fromHtml(r.getString(R.string.sms_control_message, appLabel)); 8680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 86978df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ConfirmDialogListener listener = new ConfirmDialogListener(tracker, null); 8700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AlertDialog d = new AlertDialog.Builder(mContext) 8720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setTitle(R.string.sms_control_title) 8730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setIcon(R.drawable.stat_sys_warning) 8740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setMessage(messageText) 8750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setPositiveButton(r.getString(R.string.sms_control_yes), listener) 8760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setNegativeButton(r.getString(R.string.sms_control_no), listener) 8770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setOnCancelListener(listener) 8780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .create(); 8790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 8810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.show(); 8820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Post an alert for user confirmation when sending to a potential short code. 8860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param isPremium true if the destination is known to be a premium short code 8870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker the SmsTracker for the current message. 8880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void handleConfirmShortCode(boolean isPremium, SmsTracker tracker) { 8900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (denyIfQueueLimitReached(tracker)) { 8910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; // queue limit reached; error was returned to caller 8920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8944658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int detailsId; 8950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (isPremium) { 8964658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby detailsId = R.string.sms_premium_short_code_details; 8970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 8984658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby detailsId = R.string.sms_short_code_details; 8990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9012029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra CharSequence appLabel = getAppLabel(tracker.mAppInfo.packageName); 9020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Resources r = Resources.getSystem(); 9034658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby Spanned messageText = Html.fromHtml(r.getString(R.string.sms_short_code_confirm_message, 9044658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby appLabel, tracker.mDestAddress)); 9050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9064658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 9074658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby Context.LAYOUT_INFLATER_SERVICE); 9084658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby View layout = inflater.inflate(R.layout.sms_short_code_confirmation_dialog, null); 9094658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 91078df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ConfirmDialogListener listener = new ConfirmDialogListener(tracker, 91178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt (TextView)layout.findViewById(R.id.sms_short_code_remember_undo_instruction)); 91278df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt 91378df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt 9144658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby TextView messageView = (TextView) layout.findViewById(R.id.sms_short_code_confirm_message); 9154658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby messageView.setText(messageText); 9164658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 91778df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ViewGroup detailsLayout = (ViewGroup) layout.findViewById( 9184658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby R.id.sms_short_code_detail_layout); 9194658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby TextView detailsView = (TextView) detailsLayout.findViewById( 9204658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby R.id.sms_short_code_detail_message); 9214658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby detailsView.setText(detailsId); 9224658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 9234658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby CheckBox rememberChoice = (CheckBox) layout.findViewById( 9244658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby R.id.sms_short_code_remember_choice_checkbox); 9254658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby rememberChoice.setOnCheckedChangeListener(listener); 9264658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 9270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AlertDialog d = new AlertDialog.Builder(mContext) 9284658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby .setView(layout) 9290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setPositiveButton(r.getString(R.string.sms_short_code_confirm_allow), listener) 9300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setNegativeButton(r.getString(R.string.sms_short_code_confirm_deny), listener) 9310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setOnCancelListener(listener) 9320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .create(); 9330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 9350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.show(); 9364658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 9374658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby listener.setPositiveButton(d.getButton(DialogInterface.BUTTON_POSITIVE)); 9384658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby listener.setNegativeButton(d.getButton(DialogInterface.BUTTON_NEGATIVE)); 9394658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 9404658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 9414658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby /** 9424658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * Returns the premium SMS permission for the specified package. If the package has never 9434658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * been seen before, the default {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER} 9444658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * will be returned. 9454658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @param packageName the name of the package to query permission 9464658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @return one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_UNKNOWN}, 9474658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER}, 9484658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or 9494658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW} 9504658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby */ 9514658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby public int getPremiumSmsPermission(String packageName) { 9524658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return mUsageMonitor.getPremiumSmsPermission(packageName); 9534658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 9544658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 9554658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby /** 9564658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * Sets the premium SMS permission for the specified package and save the value asynchronously 9574658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * to persistent storage. 9584658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @param packageName the name of the package to set permission 9594658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @param permission one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER}, 9604658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or 9614658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW} 9624658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby */ 9634658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby public void setPremiumSmsPermission(String packageName, int permission) { 9644658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mUsageMonitor.setPremiumSmsPermission(packageName, permission); 9650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send the message along to the radio. 9690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 9700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker holds the SMS message to send 9710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 9720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract void sendSms(SmsTracker tracker); 9730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9758d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * Send the SMS via the PSTN network. 9768d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * 9778d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * @param tracker holds the Sms tracker ready to be sent 9788d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang */ 9798d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang protected abstract void sendSmsByPstn(SmsTracker tracker); 9808d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 9818d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang /** 9821260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * Retry the message along to the radio. 9831260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * 9841260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * @param tracker holds the SMS message to send 9851260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa */ 986ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa public void sendRetrySms(SmsTracker tracker) { 987ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa // re-routing to ImsSMSDispatcher 988ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa if (mImsSMSDispatcher != null) { 989ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa mImsSMSDispatcher.sendRetrySms(tracker); 990ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } else { 991ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa Rlog.e(TAG, mImsSMSDispatcher + " is null. Retry failed"); 992ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 993ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 9941260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 9951260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** 9960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send the multi-part SMS based on multipart Sms tracker 9970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 9980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker holds the multipart Sms tracker ready to be sent 9990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void sendMultipartSms(SmsTracker tracker) { 10010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<String> parts; 10020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<PendingIntent> sentIntents; 10030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<PendingIntent> deliveryIntents; 10040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville HashMap<String, Object> map = tracker.mData; 10060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String destinationAddress = (String) map.get("destination"); 10080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String scAddress = (String) map.get("scaddress"); 10090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville parts = (ArrayList<String>) map.get("parts"); 10110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntents = (ArrayList<PendingIntent>) map.get("sentIntents"); 10120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville deliveryIntents = (ArrayList<PendingIntent>) map.get("deliveryIntents"); 10130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // check if in service 10150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int ss = mPhone.getServiceState().getState(); 10161260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // if sms over IMS is not supported on data and voice is not available... 10171260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) { 10180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0, count = parts.size(); i < count; i++) { 10190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent sentIntent = null; 10200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntents != null && sentIntents.size() > i) { 10210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent = sentIntents.get(i); 10220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleNotInService(ss, sentIntent); 10240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 10260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1028b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen sendMultipartText(destinationAddress, scAddress, parts, sentIntents, deliveryIntents, 1029b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen null/*messageUri*/, null/*callingPkg*/); 10300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Keeps track of an SMS that has been sent to the RIL, until it has 10340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * successfully been sent, or we're done trying. 10350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final class SmsTracker { 10370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // fields need to be public for derived SmsDispatchers 10380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final HashMap<String, Object> mData; 10390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int mRetryCount; 10401260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa public int mImsRetry; // nonzero indicates initial message was sent over Ims 10410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int mMessageRef; 10426ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi public boolean mExpectMore; 10431260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String mFormat; 10440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final PendingIntent mSentIntent; 10460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final PendingIntent mDeliveryIntent; 10470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10482029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra public final PackageInfo mAppInfo; 10490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final String mDestAddress; 10500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 105178d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal public final SmsHeader mSmsHeader; 105278d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal 10530217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun private long mTimestamp = System.currentTimeMillis(); 1054c99dab56e20222b28cbc6238645feac938f1c333Ye Wen public Uri mMessageUri; // Uri of persisted message if we wrote one 1055c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1056c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // Reference to states of a multipart message that this part belongs to 1057c99dab56e20222b28cbc6238645feac938f1c333Ye Wen private AtomicInteger mUnsentPartCount; 1058c99dab56e20222b28cbc6238645feac938f1c333Ye Wen private AtomicBoolean mAnyPartFailed; 10590217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 10601260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa private SmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, 1061c99dab56e20222b28cbc6238645feac938f1c333Ye Wen PendingIntent deliveryIntent, PackageInfo appInfo, String destAddr, String format, 106278d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, 10636ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi SmsHeader smsHeader, boolean isExpectMore) { 10640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mData = data; 10650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mSentIntent = sentIntent; 10660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mDeliveryIntent = deliveryIntent; 10670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRetryCount = 0; 10682029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra mAppInfo = appInfo; 10690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mDestAddress = destAddr; 10701260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mFormat = format; 10716ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi mExpectMore = isExpectMore; 10721260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mImsRetry = 0; 10731260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mMessageRef = 0; 1074c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mUnsentPartCount = unsentPartCount; 1075c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mAnyPartFailed = anyPartFailed; 1076c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mMessageUri = messageUri; 107778d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal mSmsHeader = smsHeader; 10780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Returns whether this tracker holds a multi-part SMS. 10820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the tracker holds a multi-part SMS; false otherwise 10830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby boolean isMultipart() { 10850217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun return mData.containsKey("parts"); 10860217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 10870217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 10880217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun /** 10890217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun * Persist this as a sent message 10900217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun */ 10910217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun void writeSentMessage(Context context) { 10920217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun String text = (String)mData.get("text"); 10930217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun if (text != null) { 10940217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun boolean deliveryReport = (mDeliveryIntent != null); 10950217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun // Using invalid threadId 0 here. When the message is inserted into the db, the 10960217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun // provider looks up the threadId based on the recipient(s). 1097c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mMessageUri = Sms.addMessageToUri(context.getContentResolver(), 10980217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun Telephony.Sms.Sent.CONTENT_URI, 10990217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun mDestAddress, 11000217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun text /*body*/, 11010217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun null /*subject*/, 11020217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun mTimestamp /*date*/, 11030217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun true /*read*/, 11040217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun deliveryReport /*deliveryReport*/, 11050217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 0 /*threadId*/); 11060217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 11070217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 11080217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 11090217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun /** 11100217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun * Update the status of this message if we persisted it 11110217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun */ 11120217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun public void updateSentMessageStatus(Context context, int status) { 1113c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mMessageUri != null) { 11140217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun // If we wrote this message in writeSentMessage, update it now 11150217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun ContentValues values = new ContentValues(1); 11160217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun values.put(Sms.STATUS, status); 11170217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun SqliteWrapper.update(context, context.getContentResolver(), 1118c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mMessageUri, values, null, null); 1119c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1120c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1121c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1122c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 1123c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * Update the error_code column of a message 1124c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * 1125c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param context The Context 1126c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param errorCode The error code 1127c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 1128c99dab56e20222b28cbc6238645feac938f1c333Ye Wen private void updateMessageErrorCode(Context context, int errorCode) { 1129c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mMessageUri == null) { 1130c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return; 1131c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1132c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final ContentValues values = new ContentValues(1); 1133c99dab56e20222b28cbc6238645feac938f1c333Ye Wen values.put(Sms.ERROR_CODE, errorCode); 1134c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final long identity = Binder.clearCallingIdentity(); 1135c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 1136c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (SqliteWrapper.update(context, context.getContentResolver(), mMessageUri, values, 1137c99dab56e20222b28cbc6238645feac938f1c333Ye Wen null/*where*/, null/*selectionArgs*/) != 1) { 1138c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Failed to update message error code"); 1139c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1140c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } finally { 1141c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Binder.restoreCallingIdentity(identity); 1142c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1143c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1144c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1145c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 1146c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * Set the final state of a message: FAILED or SENT 1147c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * 1148c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param context The Context 1149c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param messageType The final message type 1150c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 1151c99dab56e20222b28cbc6238645feac938f1c333Ye Wen private void setMessageFinalState(Context context, int messageType) { 1152c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mMessageUri == null) { 1153c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return; 1154c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1155c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final ContentValues values = new ContentValues(1); 1156c99dab56e20222b28cbc6238645feac938f1c333Ye Wen values.put(Sms.TYPE, messageType); 1157c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final long identity = Binder.clearCallingIdentity(); 1158c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 1159c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (SqliteWrapper.update(context, context.getContentResolver(), mMessageUri, values, 1160c99dab56e20222b28cbc6238645feac938f1c333Ye Wen null/*where*/, null/*selectionArgs*/) != 1) { 1161c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Failed to move message to " + messageType); 1162c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1163c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } finally { 1164c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Binder.restoreCallingIdentity(identity); 1165c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1166c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1167c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1168c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 1169c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * Handle a failure of a single part message or a part of a multipart message 1170c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * 1171c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param context The Context 1172c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param error The error to send back with 1173c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param errorCode 1174c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 1175c99dab56e20222b28cbc6238645feac938f1c333Ye Wen public void onFailed(Context context, int error, int errorCode) { 1176c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mAnyPartFailed != null) { 1177c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mAnyPartFailed.set(true); 1178c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1179c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // is single part or last part of multipart message 1180c99dab56e20222b28cbc6238645feac938f1c333Ye Wen boolean isSinglePartOrLastPart = true; 1181c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mUnsentPartCount != null) { 1182c99dab56e20222b28cbc6238645feac938f1c333Ye Wen isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0; 1183c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1184c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (errorCode != 0) { 1185c99dab56e20222b28cbc6238645feac938f1c333Ye Wen updateMessageErrorCode(context, errorCode); 1186c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1187c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (isSinglePartOrLastPart) { 1188c99dab56e20222b28cbc6238645feac938f1c333Ye Wen setMessageFinalState(context, Sms.MESSAGE_TYPE_FAILED); 1189c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1190c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mSentIntent != null) { 1191c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 1192fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen // Extra information to send with the sent intent 1193fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen Intent fillIn = new Intent(); 1194fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen if (mMessageUri != null) { 1195fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen // Pass this to SMS apps so that they know where it is stored 1196fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen fillIn.putExtra("uri", mMessageUri.toString()); 1197fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen } 1198c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (errorCode != 0) { 1199c99dab56e20222b28cbc6238645feac938f1c333Ye Wen fillIn.putExtra("errorCode", errorCode); 1200c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1201c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mUnsentPartCount != null && isSinglePartOrLastPart) { 1202c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // Is multipart and last part 1203c99dab56e20222b28cbc6238645feac938f1c333Ye Wen fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true); 1204c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1205c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mSentIntent.send(context, error, fillIn); 1206c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } catch (CanceledException ex) { 1207c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Failed to send result"); 1208c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1209c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1210c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1211c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1212c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 1213c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * Handle the sent of a single part message or a part of a multipart message 1214c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * 1215c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param context The Context 1216c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 1217c99dab56e20222b28cbc6238645feac938f1c333Ye Wen public void onSent(Context context) { 1218c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // is single part or last part of multipart message 1219c99dab56e20222b28cbc6238645feac938f1c333Ye Wen boolean isSinglePartOrLastPart = true; 1220c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mUnsentPartCount != null) { 1221c99dab56e20222b28cbc6238645feac938f1c333Ye Wen isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0; 1222c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1223c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (isSinglePartOrLastPart) { 1224c99dab56e20222b28cbc6238645feac938f1c333Ye Wen boolean success = true; 1225c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mAnyPartFailed != null && mAnyPartFailed.get()) { 1226c99dab56e20222b28cbc6238645feac938f1c333Ye Wen success = false; 1227c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1228c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (success) { 1229c99dab56e20222b28cbc6238645feac938f1c333Ye Wen setMessageFinalState(context, Sms.MESSAGE_TYPE_SENT); 1230c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } else { 1231c99dab56e20222b28cbc6238645feac938f1c333Ye Wen setMessageFinalState(context, Sms.MESSAGE_TYPE_FAILED); 1232c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1233c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1234c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mSentIntent != null) { 1235c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 1236fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen // Extra information to send with the sent intent 1237fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen Intent fillIn = new Intent(); 1238fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen if (mMessageUri != null) { 1239fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen // Pass this to SMS apps so that they know where it is stored 1240fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen fillIn.putExtra("uri", mMessageUri.toString()); 1241fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen } 1242c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mUnsentPartCount != null && isSinglePartOrLastPart) { 1243c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // Is multipart and last part 1244fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true); 1245c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1246fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen mSentIntent.send(context, Activity.RESULT_OK, fillIn); 1247c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } catch (CanceledException ex) { 1248c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Failed to send result"); 1249c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 12500217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 12510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1254ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected SmsTracker getSmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, 1255c99dab56e20222b28cbc6238645feac938f1c333Ye Wen PendingIntent deliveryIntent, String format, AtomicInteger unsentPartCount, 12566ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi AtomicBoolean anyPartFailed, Uri messageUri, SmsHeader smsHeader, 12576ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi boolean isExpectMore) { 12581260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Get calling app package name via UID from Binder call 12591260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa PackageManager pm = mContext.getPackageManager(); 12601260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String[] packageNames = pm.getPackagesForUid(Binder.getCallingUid()); 12611260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 12621260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Get package info via packagemanager 12631260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa PackageInfo appInfo = null; 12641260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (packageNames != null && packageNames.length > 0) { 12651260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa try { 12661260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // XXX this is lossy- apps can share a UID 12671260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa appInfo = pm.getPackageInfo(packageNames[0], PackageManager.GET_SIGNATURES); 12681260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } catch (PackageManager.NameNotFoundException e) { 12691260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // error will be logged in sendRawPdu 12701260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 12711260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 12721260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Strip non-digits from destination phone number before checking for short codes 12731260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // and before displaying the number to the user if confirmation is required. 12741260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String destAddr = PhoneNumberUtils.extractNetworkPortion((String) data.get("destAddr")); 1275c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return new SmsTracker(data, sentIntent, deliveryIntent, appInfo, destAddr, format, 12766ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi unsentPartCount, anyPartFailed, messageUri, smsHeader, isExpectMore); 1277c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1278c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1279c99dab56e20222b28cbc6238645feac938f1c333Ye Wen protected SmsTracker getSmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, 12806ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi PendingIntent deliveryIntent, String format, Uri messageUri, boolean isExpectMore) { 1281c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return getSmsTracker(data, sentIntent, deliveryIntent, format, null/*unsentPartCount*/, 12826ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi null/*anyPartFailed*/, messageUri, null/*smsHeader*/, isExpectMore); 12831260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 12841260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1285ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr, 12861260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String text, SmsMessageBase.SubmitPduBase pdu) { 12871260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa HashMap<String, Object> map = new HashMap<String, Object>(); 12881260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("destAddr", destAddr); 12891260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("scAddr", scAddr); 12901260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("text", text); 12911260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("smsc", pdu.encodedScAddress); 12921260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("pdu", pdu.encodedMessage); 12931260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa return map; 12941260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 12951260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1296ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr, 12971260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu) { 12981260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa HashMap<String, Object> map = new HashMap<String, Object>(); 12991260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("destAddr", destAddr); 13001260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("scAddr", scAddr); 1301ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa map.put("destPort", destPort); 13021260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("data", data); 13031260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("smsc", pdu.encodedScAddress); 13041260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("pdu", pdu.encodedMessage); 13051260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa return map; 13061260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 13071260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 13080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 13090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Dialog listener for SMS confirmation dialog. 13100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 13110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final class ConfirmDialogListener 13124658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, 13134658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby CompoundButton.OnCheckedChangeListener { 13140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 13150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final SmsTracker mTracker; 13164658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby private Button mPositiveButton; 13174658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby private Button mNegativeButton; 13184658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby private boolean mRememberChoice; // default is unchecked 131978df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt private final TextView mRememberUndoInstruction; 13200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 132178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ConfirmDialogListener(SmsTracker tracker, TextView textView) { 13220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mTracker = tracker; 132378df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction = textView; 13240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 13264658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby void setPositiveButton(Button button) { 13274658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mPositiveButton = button; 13284658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 13294658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 13304658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby void setNegativeButton(Button button) { 13314658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mNegativeButton = button; 13324658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 13334658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 13340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 13350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void onClick(DialogInterface dialog, int which) { 13364658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // Always set the SMS permission so that Settings will show a permission setting 13374658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // for the app (it won't be shown until after the app tries to send to a short code). 13384658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER; 13394658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 13400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (which == DialogInterface.BUTTON_POSITIVE) { 1341ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "CONFIRM sending SMS"); 13422029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // XXX this is lossy- apps can have more than one signature 1343634a24f56f54b5d2911649288147c750b67c7ae4William Luh EventLog.writeEvent(EventLogTags.EXP_DET_SMS_SENT_BY_USER, 1344ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh mTracker.mAppInfo.applicationInfo == null ? 1345ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh -1 : mTracker.mAppInfo.applicationInfo.uid); 13460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_SEND_CONFIRMED_SMS, mTracker)); 13474658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (mRememberChoice) { 13484658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW; 13494658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 13500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (which == DialogInterface.BUTTON_NEGATIVE) { 1351ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "DENY sending SMS"); 13522029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // XXX this is lossy- apps can have more than one signature 1353634a24f56f54b5d2911649288147c750b67c7ae4William Luh EventLog.writeEvent(EventLogTags.EXP_DET_SMS_DENIED_BY_USER, 1354ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh mTracker.mAppInfo.applicationInfo == null ? 1355ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh -1 : mTracker.mAppInfo.applicationInfo.uid); 13560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_STOP_SENDING, mTracker)); 13574658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (mRememberChoice) { 13584658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW; 13594658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 13600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13614658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby setPremiumSmsPermission(mTracker.mAppInfo.packageName, newSmsPermission); 13620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 13640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 13650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void onCancel(DialogInterface dialog) { 1366ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "dialog dismissed: don't send SMS"); 13670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_STOP_SENDING, mTracker)); 13680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13694658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 13704658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby @Override 13714658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1372ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "remember this choice: " + isChecked); 13734658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mRememberChoice = isChecked; 13744658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (isChecked) { 13754658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mPositiveButton.setText(R.string.sms_short_code_confirm_always_allow); 13764658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mNegativeButton.setText(R.string.sms_short_code_confirm_never_allow); 137778df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt if (mRememberUndoInstruction != null) { 137878df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction. 137978df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt setText(R.string.sms_short_code_remember_undo_instruction); 138078df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction.setPadding(0,0,0,32); 138178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt } 13824658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } else { 13834658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mPositiveButton.setText(R.string.sms_short_code_confirm_allow); 13845d875796122cdd8a7004e8e3964b20b5c65a31a1Robert Greenwalt mNegativeButton.setText(R.string.sms_short_code_confirm_deny); 138578df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt if (mRememberUndoInstruction != null) { 138678df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction.setText(""); 138778df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction.setPadding(0,0,0,0); 138878df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt } 13894658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 13904658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 13910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13921260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1393ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa public boolean isIms() { 1394ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa if (mImsSMSDispatcher != null) { 1395ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return mImsSMSDispatcher.isIms(); 1396ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } else { 1397ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa Rlog.e(TAG, mImsSMSDispatcher + " is null"); 1398ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return false; 1399ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1400ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 14011260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1402ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa public String getImsSmsFormat() { 1403ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa if (mImsSMSDispatcher != null) { 1404ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return mImsSMSDispatcher.getImsSmsFormat(); 1405ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } else { 1406ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa Rlog.e(TAG, mImsSMSDispatcher + " is null"); 1407ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return null; 1408ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1409ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1410c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1411b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville protected Uri writeOutboxMessage(int subId, String address, String text, 1412b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen boolean requireDeliveryReport, String creator) { 1413b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen final ContentValues values = new ContentValues(8); 1414c99dab56e20222b28cbc6238645feac938f1c333Ye Wen values.put(Telephony.Sms.SUB_ID, subId); 1415c99dab56e20222b28cbc6238645feac938f1c333Ye Wen values.put(Telephony.Sms.ADDRESS, address); 1416b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen values.put(Telephony.Sms.BODY, text); 1417c99dab56e20222b28cbc6238645feac938f1c333Ye Wen values.put(Telephony.Sms.DATE, System.currentTimeMillis()); // milliseconds 1418c99dab56e20222b28cbc6238645feac938f1c333Ye Wen values.put(Telephony.Sms.SEEN, 1); 1419c99dab56e20222b28cbc6238645feac938f1c333Ye Wen values.put(Telephony.Sms.READ, 1); 1420b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (!TextUtils.isEmpty(creator)) { 1421b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen values.put(Telephony.Sms.CREATOR, creator); 1422b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 1423c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (requireDeliveryReport) { 1424c99dab56e20222b28cbc6238645feac938f1c333Ye Wen values.put(Telephony.Sms.STATUS, Telephony.Sms.STATUS_PENDING); 1425c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1426c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final long identity = Binder.clearCallingIdentity(); 1427c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 1428c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final Uri uri = mContext.getContentResolver().insert( 1429c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Telephony.Sms.Outbox.CONTENT_URI, values); 1430c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return uri; 1431c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } catch (Exception e) { 1432b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Rlog.e(TAG, "writeOutboxMessage: Failed to persist outbox message", e); 1433c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return null; 1434c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } finally { 1435c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Binder.restoreCallingIdentity(identity); 1436c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1437c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1438c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1439b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville protected void moveToOutbox(int subId, Uri messageUri, String creator) { 1440b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen final ContentValues values = new ContentValues(4); 1441b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen values.put(Telephony.Sms.SUB_ID, subId); 1442b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (!TextUtils.isEmpty(creator)) { 1443b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen // Reset creator/sender 1444b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen values.put(Telephony.Sms.CREATOR, creator); 1445b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 1446b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen // Reset the timestamp 1447b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen values.put(Telephony.Sms.DATE, System.currentTimeMillis()); // milliseconds 1448b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen values.put(Telephony.Sms.TYPE, Telephony.Sms.MESSAGE_TYPE_OUTBOX); 1449b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen final long identity = Binder.clearCallingIdentity(); 1450b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen try { 1451b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (mContext.getContentResolver().update(messageUri, values, 1452b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen null/*where*/, null/*selectionArgs*/) != 1) { 1453b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Rlog.e(TAG, "moveToOutbox: failed to update message " + messageUri); 1454b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 1455b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } catch (Exception e) { 1456b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Rlog.e(TAG, "moveToOutbox: Failed to update message", e); 1457b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } finally { 1458b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Binder.restoreCallingIdentity(identity); 1459b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 1460b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 1461b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen 1462c99dab56e20222b28cbc6238645feac938f1c333Ye Wen private String getMultipartMessageText(ArrayList<String> parts) { 1463c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final StringBuilder sb = new StringBuilder(); 1464c99dab56e20222b28cbc6238645feac938f1c333Ye Wen for (String part : parts) { 1465c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (part != null) { 1466c99dab56e20222b28cbc6238645feac938f1c333Ye Wen sb.append(part); 1467c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1468c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1469c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return sb.toString(); 1470c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1471b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen 1472c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal protected String getCarrierAppPackageName(Intent intent) { 1473a9552aa6bf3ce12c75ad43165034d9a1233fb131Shishir Agrawal UiccCard card = UiccController.getInstance().getUiccCard(); 14747f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal if (card == null) { 14757f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal return null; 14767f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal } 14777f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal 1478934a24a6aa2b7a981e872fa350648904ed80280aDiego Pontoriero List<String> carrierPackages = card.getCarrierPackageNamesForIntent( 1479c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal mContext.getPackageManager(), intent); 14807f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal return (carrierPackages != null && carrierPackages.size() == 1) ? 14817f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal carrierPackages.get(0) : null; 14827f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal 1483c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal } 1484c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal 1485b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville protected int getSubId() { 1486b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen return SubscriptionController.getInstance().getSubIdUsingPhoneId(mPhone.mPhoneId); 1487b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 14880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville} 1489