SMSDispatcher.java revision 8d8e8f45200d17b78d196d8cba389fd9c547ac11
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 Saville 190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.Activity; 200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.AlertDialog; 210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.PendingIntent; 220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.PendingIntent.CanceledException; 238d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport android.content.BroadcastReceiver; 240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.ContentResolver; 250217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.content.ContentValues; 260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Context; 270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.DialogInterface; 280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Intent; 290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.ApplicationInfo; 302029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condraimport android.content.pm.PackageInfo; 310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.PackageManager; 320825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.res.Resources; 33ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwaltimport android.database.ContentObserver; 340217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.database.sqlite.SqliteWrapper; 350217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.net.Uri; 360825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult; 370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Binder; 388d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport android.os.Bundle; 390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler; 400825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message; 410825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.SystemProperties; 42ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwaltimport android.provider.Settings; 430217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.provider.Telephony; 440217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.provider.Telephony.Sms; 458d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport android.provider.Telephony.Sms.Intents; 460825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.PhoneNumberUtils; 470d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.Rlog; 480825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.ServiceState; 490825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.TelephonyManager; 500825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.Html; 510825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.Spanned; 522029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condraimport android.util.EventLog; 534658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.view.LayoutInflater; 544658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.view.View; 5578df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwaltimport android.view.ViewGroup; 560825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.WindowManager; 574658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.Button; 584658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.CheckBox; 594658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.CompoundButton; 604658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.TextView; 610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 620825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.R; 630825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; 64ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowaimport com.android.internal.telephony.ImsSMSDispatcher; 650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 660825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList; 678d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport java.util.Collections; 680825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.HashMap; 698d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport java.util.List; 700825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Random; 710d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.util.concurrent.atomic.AtomicInteger; 720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 730825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE; 740825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_GENERIC_FAILURE; 750825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_LIMIT_EXCEEDED; 760825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_NO_SERVICE; 770825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_NULL_PDU; 780825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_RADIO_OFF; 790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 800825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic abstract class SMSDispatcher extends Handler { 81cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville static final String TAG = "SMSDispatcher"; // accessed from inner class 82cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville static final boolean DBG = false; 830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String SEND_NEXT_MSG_EXTRA = "SendNextMsg"; 840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Permission required to send SMS to short codes without user confirmation. */ 860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String SEND_SMS_NO_CONFIRMATION_PERMISSION = 870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "android.permission.SEND_SMS_NO_CONFIRMATION"; 880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 89ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private static final int PREMIUM_RULE_USE_SIM = 1; 90ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private static final int PREMIUM_RULE_USE_NETWORK = 2; 91ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private static final int PREMIUM_RULE_USE_BOTH = 3; 92ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private final AtomicInteger mPremiumSmsRule = new AtomicInteger(PREMIUM_RULE_USE_SIM); 93ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private final SettingsObserver mSettingsObserver; 94ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** SMS send complete. */ 960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final int EVENT_SEND_SMS_COMPLETE = 2; 970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Retry sending a previously failed SMS message */ 990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_SEND_RETRY = 3; 1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Confirmation required for sending a large number of messages. */ 1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_SEND_LIMIT_REACHED_CONFIRMATION = 4; 1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Send the user confirmed SMS */ 1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville static final int EVENT_SEND_CONFIRMED_SMS = 5; // accessed from inner class 1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Don't send SMS (user did not confirm). */ 1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville static final int EVENT_STOP_SENDING = 7; // accessed from inner class 1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Confirmation required for third-party apps sending to an SMS short code. */ 1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE = 8; 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_PREMIUM_SHORT_CODE = 9; 1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** Handle status report from {@code CdmaInboundSmsHandler}. */ 1170d4bcdf379842af4b6304809156971e926f374f0Jake Hamby protected static final int EVENT_HANDLE_STATUS_REPORT = 10; 1180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 1191260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** Radio is ON */ 1201260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_RADIO_ON = 11; 1211260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** IMS registration/SMS format changed */ 1231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_IMS_STATE_CHANGED = 12; 1241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1251260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** Callback from RIL_REQUEST_IMS_REGISTRATION_STATE */ 1261260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_IMS_STATE_DONE = 13; 1271260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1281260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // other 1291260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_NEW_ICC_SMS = 14; 1301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_ICC_CHANGED = 15; 1311260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1321260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected PhoneBase mPhone; 1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected final Context mContext; 1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected final ContentResolver mResolver; 13522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville protected final CommandsInterface mCi; 1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected final TelephonyManager mTelephonyManager; 1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Maximum number of times to retry sending a failed SMS. */ 1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int MAX_SEND_RETRIES = 3; 1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Delay before next send attempt on a failed SMS, in milliseconds. */ 1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int SEND_RETRY_DELAY = 2000; 1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** single part SMS */ 1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int SINGLE_PART_SMS = 1; 1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Message sending queue limit */ 1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int MO_MSG_QUEUE_LIMIT = 5; 1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Message reference for a CONCATENATED_8_BIT_REFERENCE or 1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * CONCATENATED_16_BIT_REFERENCE message set. Should be 1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * incremented for each set of concatenated messages. 1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Static field shared by all dispatcher objects. 1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static int sConcatenatedRef = new Random().nextInt(256); 1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Outgoing message counter. Shared by all dispatchers. */ 1561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa private SmsUsageMonitor mUsageMonitor; 1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 158ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa private ImsSMSDispatcher mImsSMSDispatcher; 159ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa 1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Number of outgoing SmsTrackers waiting for user confirmation. */ 1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private int mPendingTrackerCount; 1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* Flags indicating whether the current device allows sms service */ 1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected boolean mSmsCapable = true; 1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected boolean mSmsSendDisabled; 1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected int mRemainingMessages = -1; 1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static int getNextConcatenatedRef() { 1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sConcatenatedRef += 1; 1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return sConcatenatedRef; 1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Create a new SMS dispatcher. 1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param phone the Phone to use 1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param usageMonitor the SmsUsageMonitor to use 1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 179ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected SMSDispatcher(PhoneBase phone, SmsUsageMonitor usageMonitor, 180ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa ImsSMSDispatcher imsSMSDispatcher) { 1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhone = phone; 182ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa mImsSMSDispatcher = imsSMSDispatcher; 1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mContext = phone.getContext(); 1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mResolver = mContext.getContentResolver(); 18522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi = phone.mCi; 1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mUsageMonitor = usageMonitor; 1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 188ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mSettingsObserver = new SettingsObserver(this, mPremiumSmsRule, mContext); 189ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor( 190ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt Settings.Global.SMS_SHORT_CODE_RULE), false, mSettingsObserver); 1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mSmsCapable = mContext.getResources().getBoolean( 1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville com.android.internal.R.bool.config_sms_capable); 1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mSmsSendDisabled = !SystemProperties.getBoolean( 1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TelephonyProperties.PROPERTY_SMS_SEND, mSmsCapable); 196ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "SMSDispatcher: ctor mSmsCapable=" + mSmsCapable + " format=" + getFormat() 1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville + " mSmsSendDisabled=" + mSmsSendDisabled); 1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 200ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt /** 201ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt * Observe the secure setting for updated premium sms determination rules 202ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt */ 203ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private static class SettingsObserver extends ContentObserver { 204ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private final AtomicInteger mPremiumSmsRule; 205ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private final Context mContext; 206ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt SettingsObserver(Handler handler, AtomicInteger premiumSmsRule, Context context) { 207ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt super(handler); 208ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mPremiumSmsRule = premiumSmsRule; 209ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mContext = context; 210ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt onChange(false); // load initial value; 211ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 212ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 213ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt @Override 214ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt public void onChange(boolean selfChange) { 215ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mPremiumSmsRule.set(Settings.Global.getInt(mContext.getContentResolver(), 216ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt Settings.Global.SMS_SHORT_CODE_RULE, PREMIUM_RULE_USE_SIM)); 217ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 218ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 219ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 2201260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected void updatePhoneObject(PhoneBase phone) { 2211260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mPhone = phone; 2221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mUsageMonitor = phone.mSmsUsageMonitor; 2231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa Rlog.d(TAG, "Active phone changed to " + mPhone.getPhoneName() ); 2241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 2251260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Unregister for incoming SMS events. */ 2270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby public void dispose() { 2280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); 2290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The format of the message PDU in the associated broadcast intent. 2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * This will be either "3gpp" for GSM/UMTS/LTE messages in 3GPP format 2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or "3gpp2" for CDMA/LTE messages in 3GPP2 format. 2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Note: All applications which handle incoming SMS messages by processing the 2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * SMS_RECEIVED_ACTION broadcast intent MUST pass the "format" extra from the intent 2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * into the new methods in {@link android.telephony.SmsMessage} which take an 2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * extra format parameter. This is required in order to correctly decode the PDU on 2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * devices which require support for both 3GPP and 3GPP2 formats at the same time, 2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * such as CDMA/LTE devices and GSM/CDMA world phones. 2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return the format of the message PDU 2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract String getFormat(); 2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 2480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Pass the Message object to subclass to handle. Currently used to pass CDMA status reports 2490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * from {@link com.android.internal.telephony.cdma.CdmaInboundSmsHandler}. 2500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @param o the SmsMessage containing the status report 2510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 2520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby protected void handleStatusReport(Object o) { 2530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.d(TAG, "handleStatusReport() called with no subclass."); 2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* TODO: Need to figure out how to keep track of status report routing in a 2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * persistent manner. If the phone process restarts (reboot or crash), 2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * we will lose this list and any status reports that come in after 2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * will be dropped. 2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Sent messages awaiting a delivery status report. */ 2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected final ArrayList<SmsTracker> deliveryPendingList = new ArrayList<SmsTracker>(); 2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2648d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang /** Outgoing messages being handled by the carrier app. */ 2658d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang protected final List<SmsTracker> sendPendingList = 2668d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Collections.synchronizedList(new ArrayList<SmsTracker>()); 2678d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Handles events coming from the phone stack. Overridden from handler. 2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param msg the message to handle 2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void handleMessage(Message msg) { 2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (msg.what) { 2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_SMS_COMPLETE: 2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // An outbound SMS has been successfully transferred, or failed. 2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleSendComplete((AsyncResult) msg.obj); 2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_RETRY: 2821260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa Rlog.d(TAG, "SMS retry.."); 2831260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa sendRetrySms((SmsTracker) msg.obj); 2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_LIMIT_REACHED_CONFIRMATION: 2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleReachSentLimit((SmsTracker)(msg.obj)); 2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE: 2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleConfirmShortCode(false, (SmsTracker)(msg.obj)); 2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE: 2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleConfirmShortCode(true, (SmsTracker)(msg.obj)); 2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_CONFIRMED_SMS: 2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsTracker tracker = (SmsTracker) msg.obj; 3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (tracker.isMultipart()) { 3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMultipartSms(tracker); 3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendSms(tracker); 3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPendingTrackerCount--; 3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_STOP_SENDING: 3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsTracker tracker = (SmsTracker) msg.obj; 3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (tracker.mSentIntent != null) { 3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tracker.mSentIntent.send(RESULT_ERROR_LIMIT_EXCEEDED); 3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CanceledException ex) { 317ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "failed to send RESULT_ERROR_LIMIT_EXCEEDED"); 3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 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 3554931e2c19616ab5985f61f343b231efb33692241Zhihai Xu if (SmsApplication.shouldWriteMessageForPackage( 3564931e2c19616ab5985f61f343b231efb33692241Zhihai Xu tracker.mAppInfo.applicationInfo.packageName, mContext)) { 3574931e2c19616ab5985f61f343b231efb33692241Zhihai Xu // Persist it into the SMS database as a sent message 3584931e2c19616ab5985f61f343b231efb33692241Zhihai Xu // so the user can see it in their default app. 3590217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun tracker.writeSentMessage(mContext); 3600217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 3610217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (tracker.mDeliveryIntent != null) { 3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Expecting a status report. Add it to the list. 3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville deliveryPendingList.add(tracker); 3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntent != null) { 3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mRemainingMessages > -1) { 3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRemainingMessages--; 3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mRemainingMessages == 0) { 3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Intent sendNext = new Intent(); 3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendNext.putExtra(SEND_NEXT_MSG_EXTRA, true); 3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(mContext, Activity.RESULT_OK, sendNext); 3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(Activity.RESULT_OK); 3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CanceledException ex) {} 3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 383cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville if (DBG) Rlog.d(TAG, "SMS send failed"); 3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int ss = mPhone.getServiceState().getState(); 3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3871260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if ( tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) { 3881260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // This is retry after failure over IMS but voice is not available. 3891260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Set retry to max allowed, so no retry is sent and 3901260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // cause RESULT_ERROR_GENERIC_FAILURE to be returned to app. 3911260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa tracker.mRetryCount = MAX_SEND_RETRIES; 3921260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 3931260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa Rlog.d(TAG, "handleSendComplete: Skipping retry: " 3941260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" isIms()="+isIms() 3951260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" mRetryCount="+tracker.mRetryCount 3961260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" mImsRetry="+tracker.mImsRetry 3971260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" mMessageRef="+tracker.mMessageRef 3981260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" SS= "+mPhone.getServiceState().getState()); 3991260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 4001260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 4011260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // if sms over IMS is not supported on data and voice is not available... 4021260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) { 4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleNotInService(ss, tracker.mSentIntent); 4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if ((((CommandException)(ar.exception)).getCommandError() 4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville == CommandException.Error.SMS_FAIL_RETRY) && 4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tracker.mRetryCount < MAX_SEND_RETRIES) { 4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Retry after a delay if needed. 4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TODO: According to TS 23.040, 9.2.3.6, we should resend 4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // with the same TP-MR as the failed message, and 4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TP-RD set to 1. However, we don't have a means of 4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // knowing the MR for the failed message (EF_SMSstatus 4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // may or may not have the MR corresponding to this 4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // message, depending on the failure). Also, in some 4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // implementations this retry is handled by the baseband. 4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tracker.mRetryCount++; 4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker); 4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessageDelayed(retryMsg, SEND_RETRY_DELAY); 4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (tracker.mSentIntent != null) { 4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int error = RESULT_ERROR_GENERIC_FAILURE; 4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (((CommandException)(ar.exception)).getCommandError() 4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville == CommandException.Error.FDN_CHECK_FAILURE) { 4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville error = RESULT_ERROR_FDN_CHECK_FAILURE; 4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Done retrying; return an error to the app. 4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Intent fillIn = new Intent(); 4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.result != null) { 42922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville fillIn.putExtra("errorCode", ((SmsResponse)ar.result).mErrorCode); 4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mRemainingMessages > -1) { 4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRemainingMessages--; 4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mRemainingMessages == 0) { 4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true); 4370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tracker.mSentIntent.send(mContext, error, fillIn); 4400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CanceledException ex) {} 4410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Handles outbound message when the phone is not in service. 4470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param ss Current service state. Valid values are: 4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * OUT_OF_SERVICE 4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * EMERGENCY_ONLY 4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * POWER_OFF 4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntent the PendingIntent to send the error to 4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static void handleNotInService(int ss, PendingIntent sentIntent) { 4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntent != null) { 4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ss == ServiceState.STATE_POWER_OFF) { 4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(RESULT_ERROR_RADIO_OFF); 4590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 4600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(RESULT_ERROR_NO_SERVICE); 4610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CanceledException ex) {} 4630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 4670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a data based SMS to a specific application port. 4680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 4690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param destAddr the address to send the message to 4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddr is the service center address or null to use 4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the current default SMSC 4720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param destPort the port to deliver the message to 4730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param data the body of the message to send 4740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntent if not NULL this <code>PendingIntent</code> is 4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is successfully sent, or failed. 4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors:<br> 4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code><br> 4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code><br> 4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code><br>. 4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 4830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the extra "errorCode" containing a radio technology specific value, 4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * generally only useful for troubleshooting.<br> 4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is delivered to the recipient. The 4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * raw pdu of the status report is in the extended data ("pdu"). 4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract void sendData(String destAddr, String scAddr, int destPort, 4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent); 4940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a text based SMS. 4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 4980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param destAddr the address to send the message to 4990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddr is the service center address or null to use 5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the current default SMSC 5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param text the body of the message to send 5020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntent if not NULL this <code>PendingIntent</code> is 5030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is successfully sent, or failed. 5040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 5050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors:<br> 5060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code><br> 5080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code><br> 5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code><br>. 5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the extra "errorCode" containing a radio technology specific value, 5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * generally only useful for troubleshooting.<br> 5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is delivered to the recipient. The 5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * raw pdu of the status report is in the extended data ("pdu"). 5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract void sendText(String destAddr, String scAddr, 5210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String text, PendingIntent sentIntent, PendingIntent deliveryIntent); 5220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 5240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Calculate the number of septets needed to encode the message. 5250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 5260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param messageBody the message to encode 5270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param use7bitOnly ignore (but still count) illegal characters if true 5280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return TextEncodingDetails 5290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 5300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract TextEncodingDetails calculateLength(CharSequence messageBody, 5310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean use7bitOnly); 5320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 5348d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * Update the status of a pending (send-by-IP) SMS message and resend by PSTN if necessary. 5358d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * This outbound message was handled by the carrier app. If the carrier app fails to send 5368d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * this message, it would be resent by PSTN. 5378d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * 5388d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * @param messageRef the reference number of the SMS message. 5398d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * @param success True if and only if the message was sent successfully. If its value is 5408d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * false, this message should be resent via PSTN. 5418d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang */ 5428d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang protected abstract void updateSmsSendStatus(int messageRef, boolean success); 5438d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 5448d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang /** 5458d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * Handler for a {@link GsmSMSDispatcher} or {@link CdmaSMSDispatcher} broadcast. 5468d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * If SMS sending is successfuly, sends EVENT_SEND_SMS_COMPLETE message. Otherwise, 5478d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * send the message via the GSM/CDMA network. 5488d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang */ 5498d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang protected final class SMSDispatcherReceiver extends BroadcastReceiver { 5508d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 5518d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang private final SmsTracker mTracker; 5528d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 5538d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang public SMSDispatcherReceiver(SmsTracker tracker) { 5548d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang mTracker = tracker; 5558d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } 5568d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 5578d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang @Override 5588d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang public void onReceive(Context context, Intent intent) { 5598d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang String action = intent.getAction(); 5608d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang if (action.equals(Intents.SMS_SEND_ACTION)) { 5618d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang int rc = getResultCode(); 5628d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang if (rc == Activity.RESULT_OK) { 5638d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Rlog.d(TAG, "Sending SMS by IP pending."); 5648d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Bundle resultExtras = getResultExtras(false); 5658d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang if (resultExtras != null && resultExtras.containsKey("messageref")) { 5668d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang mTracker.mMessageRef = resultExtras.getInt("messageref"); 5678d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Rlog.d(TAG, "messageref = " + mTracker.mMessageRef); 5688d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } else { 5698d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Rlog.e(TAG, "Can't find messageref in result extras."); 5708d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } 5718d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang sendPendingList.add(mTracker); 5728d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } else { 5738d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Rlog.d(TAG, "Sending SMS by IP failed."); 5748d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang sendSmsByPstn(mTracker); 5758d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } 5768d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } else { 5778d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang Rlog.e(TAG, "unexpected BroadcastReceiver action: " + action); 5788d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } 5798d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } 5808d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang } 5818d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 5828d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang /** 5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a multi-part text based SMS. 5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param destAddr the address to send the message to 5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddr is the service center address or null to use 5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the current default SMSC 5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param parts an <code>ArrayList</code> of strings that, in order, 5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * comprise the original message 5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntents if not null, an <code>ArrayList</code> of 5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>PendingIntent</code>s (one for each message part) that is 5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the corresponding message part has been sent. 5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors: 5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code> 5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code> 5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code> 5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code>. 5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 6020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param deliveryIntents if not null, an <code>ArrayList</code> of 6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>PendingIntent</code>s (one for each message part) that is 6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the corresponding message part has been delivered 6050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * to the recipient. The raw pdu of the status report is in the 6060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * extended data ("pdu"). 6070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 6080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void sendMultipartText(String destAddr, String scAddr, 6090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, 6100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<PendingIntent> deliveryIntents) { 6110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int refNumber = getNextConcatenatedRef() & 0x00FF; 6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int msgCount = parts.size(); 6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int encoding = SmsConstants.ENCODING_UNKNOWN; 6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRemainingMessages = msgCount; 6170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount]; 6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < msgCount; i++) { 6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TextEncodingDetails details = calculateLength(parts.get(i), false); 6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (encoding != details.codeUnitSize 6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville && (encoding == SmsConstants.ENCODING_UNKNOWN 6230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville || encoding == SmsConstants.ENCODING_7BIT)) { 6240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encoding = details.codeUnitSize; 6250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodingForParts[i] = details; 6270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < msgCount; i++) { 6300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); 6310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.refNumber = refNumber; 6320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.seqNumber = i + 1; // 1-based sequence 6330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.msgCount = msgCount; 6340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TODO: We currently set this to true since our messaging app will never 6350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // send more than 255 parts (it converts the message to MMS well before that). 6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // However, we should support 3rd party messaging apps that might need 16-bit 6370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // references 6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Note: It's not sufficient to just flip this bit to true; it will have 6390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // ripple effects (several calculations assume 8-bit ref). 6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.isEightBits = true; 6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsHeader smsHeader = new SmsHeader(); 6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsHeader.concatRef = concatRef; 6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Set the national language tables for 3GPP 7-bit encoding, if enabled. 6450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (encoding == SmsConstants.ENCODING_7BIT) { 6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsHeader.languageTable = encodingForParts[i].languageTable; 6470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable; 6480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent sentIntent = null; 6510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntents != null && sentIntents.size() > i) { 6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent = sentIntents.get(i); 6530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent deliveryIntent = null; 6560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (deliveryIntents != null && deliveryIntents.size() > i) { 6570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville deliveryIntent = deliveryIntents.get(i); 6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendNewSubmitPdu(destAddr, scAddr, parts.get(i), smsHeader, encoding, 6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent, deliveryIntent, (i == (msgCount - 1))); 6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 6670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Create a new SubmitPdu and send it. 6680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 6690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract void sendNewSubmitPdu(String destinationAddress, String scAddress, 6700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String message, SmsHeader smsHeader, int encoding, 6710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart); 6720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 6740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a SMS 6751260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * @param tracker will contain: 6761260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -smsc the SMSC to send the message through, or NULL for the 6770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * default SMSC 6781260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -pdu the raw PDU to send 6791260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -sentIntent if not NULL this <code>Intent</code> is 6800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is successfully sent, or failed. 6810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 6820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors: 6830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code> 6840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code> 6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code> 6860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code>. 6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 6901260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -deliveryIntent if not NULL this <code>Intent</code> is 6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is delivered to the recipient. The 6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * raw pdu of the status report is in the extended data ("pdu"). 6931260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -param destAddr the destination phone number (for short code confirmation) 6940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 6951260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected void sendRawPdu(SmsTracker tracker) { 6961260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa HashMap map = tracker.mData; 6971260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa byte pdu[] = (byte[]) map.get("pdu"); 6981260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 6991260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa PendingIntent sentIntent = tracker.mSentIntent; 7000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mSmsSendDisabled) { 7010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntent != null) { 7020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(RESULT_ERROR_NO_SERVICE); 7040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CanceledException ex) {} 7050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 706ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "Device does not support sending sms."); 7070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 7080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (pdu == null) { 7110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntent != null) { 7120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 7130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(RESULT_ERROR_NULL_PDU); 7140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CanceledException ex) {} 7150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 7170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Get calling app package name via UID from Binder call 7200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PackageManager pm = mContext.getPackageManager(); 7210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String[] packageNames = pm.getPackagesForUid(Binder.getCallingUid()); 7220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (packageNames == null || packageNames.length == 0) { 7240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Refuse to send SMS if we can't get the calling package name. 725ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get calling app package name: refusing to send SMS"); 7260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntent != null) { 7270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 7280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(RESULT_ERROR_GENERIC_FAILURE); 7290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CanceledException ex) { 730ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "failed to send error result"); 7310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 7340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7362029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // Get package info via packagemanager 7370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby PackageInfo appInfo; 7382029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra try { 7392029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // XXX this is lossy- apps can share a UID 7402029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra appInfo = pm.getPackageInfo(packageNames[0], PackageManager.GET_SIGNATURES); 7412029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra } catch (PackageManager.NameNotFoundException e) { 742ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get calling app package info: refusing to send SMS"); 7432029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra if (sentIntent != null) { 7442029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra try { 7452029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra sentIntent.send(RESULT_ERROR_GENERIC_FAILURE); 7462029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra } catch (CanceledException ex) { 747ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "failed to send error result"); 7482029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra } 7492029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra } 7502029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra return; 7512029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra } 7520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // checkDestination() returns true if the destination is not a premium short code or the 7540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // sending app is approved to send to short codes. Otherwise, a message is sent to our 7550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // handler with the SmsTracker to request user confirmation before sending. 7560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (checkDestination(tracker)) { 7570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // check for excessive outgoing SMS usage by this app 7582029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra if (!mUsageMonitor.check(appInfo.packageName, SINGLE_PART_SMS)) { 7590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, tracker)); 7600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 7610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int ss = mPhone.getServiceState().getState(); 7640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7651260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // if sms over IMS is not supported on data and voice is not available... 7661260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) { 7670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleNotInService(ss, tracker.mSentIntent); 7680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 7690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendSms(tracker); 7700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 7750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Check if destination is a potential premium short code and sender is not pre-approved to 7760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * send to short codes. 7770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 7780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker the tracker for the SMS to send 7790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the destination is approved; false if user confirmation event was sent 7800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 7810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean checkDestination(SmsTracker tracker) { 7820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mContext.checkCallingOrSelfPermission(SEND_SMS_NO_CONFIRMATION_PERMISSION) 7830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville == PackageManager.PERMISSION_GRANTED) { 7840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return true; // app is pre-approved to send to short codes 7850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 786ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt int rule = mPremiumSmsRule.get(); 787ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt int smsCategory = SmsUsageMonitor.CATEGORY_NOT_SHORT_CODE; 788ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (rule == PREMIUM_RULE_USE_SIM || rule == PREMIUM_RULE_USE_BOTH) { 789ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt String simCountryIso = mTelephonyManager.getSimCountryIso(); 790ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (simCountryIso == null || simCountryIso.length() != 2) { 791ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get SIM country Iso: trying network country Iso"); 792ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt simCountryIso = mTelephonyManager.getNetworkCountryIso(); 793ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 794ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 795ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt smsCategory = mUsageMonitor.checkDestination(tracker.mDestAddress, simCountryIso); 796ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 797ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (rule == PREMIUM_RULE_USE_NETWORK || rule == PREMIUM_RULE_USE_BOTH) { 798ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt String networkCountryIso = mTelephonyManager.getNetworkCountryIso(); 799ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (networkCountryIso == null || networkCountryIso.length() != 2) { 800ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get Network country Iso: trying SIM country Iso"); 801ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt networkCountryIso = mTelephonyManager.getSimCountryIso(); 802ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 803ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 804cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville smsCategory = SmsUsageMonitor.mergeShortCodeCategories(smsCategory, 805ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mUsageMonitor.checkDestination(tracker.mDestAddress, networkCountryIso)); 8060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 808ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (smsCategory == SmsUsageMonitor.CATEGORY_NOT_SHORT_CODE 809ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt || smsCategory == SmsUsageMonitor.CATEGORY_FREE_SHORT_CODE 810ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt || smsCategory == SmsUsageMonitor.CATEGORY_STANDARD_SHORT_CODE) { 8114658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return true; // not a premium short code 8124658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 8134658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 8144658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // Wait for user confirmation unless the user has set permission to always allow/deny 8154658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int premiumSmsPermission = mUsageMonitor.getPremiumSmsPermission( 8164658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby tracker.mAppInfo.packageName); 8174658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (premiumSmsPermission == SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) { 8184658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // First time trying to send to premium SMS. 8194658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby premiumSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER; 8204658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 8210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8224658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby switch (premiumSmsPermission) { 8234658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW: 824ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "User approved this app to send to premium SMS"); 8254658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return true; 8260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8274658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW: 828ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.w(TAG, "User denied this app from sending to premium SMS"); 8294658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby sendMessage(obtainMessage(EVENT_STOP_SENDING, tracker)); 8304658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return false; // reject this message 8314658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 8324658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER: 8330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville default: 8344658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int event; 835ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt if (smsCategory == SmsUsageMonitor.CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE) { 8364658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby event = EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE; 8374658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } else { 8384658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby event = EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE; 8394658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 8404658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby sendMessage(obtainMessage(event, tracker)); 8414658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return false; // wait for user confirmation 8420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Deny sending an SMS if the outgoing queue limit is reached. Used when the message 8480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * must be confirmed by the user due to excessive usage or potential premium SMS detected. 8490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker the SmsTracker for the message to send 8500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the message was denied; false to continue with send confirmation 8510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean denyIfQueueLimitReached(SmsTracker tracker) { 8530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mPendingTrackerCount >= MO_MSG_QUEUE_LIMIT) { 8540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Deny sending message when the queue limit is reached. 8550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 856a13eb8b86f22b0efcfb888e2491b007d3424ddddRekha Kumar if (tracker.mSentIntent != null) { 857a13eb8b86f22b0efcfb888e2491b007d3424ddddRekha Kumar tracker.mSentIntent.send(RESULT_ERROR_LIMIT_EXCEEDED); 858a13eb8b86f22b0efcfb888e2491b007d3424ddddRekha Kumar } 8590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CanceledException ex) { 860ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "failed to send back RESULT_ERROR_LIMIT_EXCEEDED"); 8610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return true; 8630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPendingTrackerCount++; 8650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return false; 8660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Returns the label for the specified app package name. 8700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param appPackage the package name of the app requesting to send an SMS 8710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return the label for the specified app, or the package name if getApplicationInfo() fails 8720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private CharSequence getAppLabel(String appPackage) { 8740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PackageManager pm = mContext.getPackageManager(); 8750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 8760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ApplicationInfo appInfo = pm.getApplicationInfo(appPackage, 0); 8770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return appInfo.loadLabel(pm); 8780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (PackageManager.NameNotFoundException e) { 879ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "PackageManager Name Not Found for package " + appPackage); 8800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return appPackage; // fall back to package name if we can't get app label 8810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Post an alert when SMS needs confirmation due to excessive usage. 8860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker an SmsTracker for the current message. 8870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void handleReachSentLimit(SmsTracker tracker) { 8890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (denyIfQueueLimitReached(tracker)) { 8900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; // queue limit reached; error was returned to caller 8910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8932029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra CharSequence appLabel = getAppLabel(tracker.mAppInfo.packageName); 8940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Resources r = Resources.getSystem(); 8950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Spanned messageText = Html.fromHtml(r.getString(R.string.sms_control_message, appLabel)); 8960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 89778df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ConfirmDialogListener listener = new ConfirmDialogListener(tracker, null); 8980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AlertDialog d = new AlertDialog.Builder(mContext) 9000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setTitle(R.string.sms_control_title) 9010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setIcon(R.drawable.stat_sys_warning) 9020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setMessage(messageText) 9030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setPositiveButton(r.getString(R.string.sms_control_yes), listener) 9040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setNegativeButton(r.getString(R.string.sms_control_no), listener) 9050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setOnCancelListener(listener) 9060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .create(); 9070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 9090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.show(); 9100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Post an alert for user confirmation when sending to a potential short code. 9140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param isPremium true if the destination is known to be a premium short code 9150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker the SmsTracker for the current message. 9160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 9170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void handleConfirmShortCode(boolean isPremium, SmsTracker tracker) { 9180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (denyIfQueueLimitReached(tracker)) { 9190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; // queue limit reached; error was returned to caller 9200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9224658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int detailsId; 9230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (isPremium) { 9244658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby detailsId = R.string.sms_premium_short_code_details; 9250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 9264658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby detailsId = R.string.sms_short_code_details; 9270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9292029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra CharSequence appLabel = getAppLabel(tracker.mAppInfo.packageName); 9300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Resources r = Resources.getSystem(); 9314658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby Spanned messageText = Html.fromHtml(r.getString(R.string.sms_short_code_confirm_message, 9324658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby appLabel, tracker.mDestAddress)); 9330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9344658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 9354658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby Context.LAYOUT_INFLATER_SERVICE); 9364658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby View layout = inflater.inflate(R.layout.sms_short_code_confirmation_dialog, null); 9374658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 93878df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ConfirmDialogListener listener = new ConfirmDialogListener(tracker, 93978df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt (TextView)layout.findViewById(R.id.sms_short_code_remember_undo_instruction)); 94078df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt 94178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt 9424658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby TextView messageView = (TextView) layout.findViewById(R.id.sms_short_code_confirm_message); 9434658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby messageView.setText(messageText); 9444658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 94578df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ViewGroup detailsLayout = (ViewGroup) layout.findViewById( 9464658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby R.id.sms_short_code_detail_layout); 9474658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby TextView detailsView = (TextView) detailsLayout.findViewById( 9484658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby R.id.sms_short_code_detail_message); 9494658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby detailsView.setText(detailsId); 9504658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 9514658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby CheckBox rememberChoice = (CheckBox) layout.findViewById( 9524658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby R.id.sms_short_code_remember_choice_checkbox); 9534658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby rememberChoice.setOnCheckedChangeListener(listener); 9544658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 9550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AlertDialog d = new AlertDialog.Builder(mContext) 9564658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby .setView(layout) 9570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setPositiveButton(r.getString(R.string.sms_short_code_confirm_allow), listener) 9580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setNegativeButton(r.getString(R.string.sms_short_code_confirm_deny), listener) 9590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setOnCancelListener(listener) 9600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .create(); 9610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 9630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.show(); 9644658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 9654658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby listener.setPositiveButton(d.getButton(DialogInterface.BUTTON_POSITIVE)); 9664658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby listener.setNegativeButton(d.getButton(DialogInterface.BUTTON_NEGATIVE)); 9674658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 9684658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 9694658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby /** 9704658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * Returns the premium SMS permission for the specified package. If the package has never 9714658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * been seen before, the default {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER} 9724658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * will be returned. 9734658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @param packageName the name of the package to query permission 9744658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @return one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_UNKNOWN}, 9754658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER}, 9764658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or 9774658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW} 9784658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby */ 9794658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby public int getPremiumSmsPermission(String packageName) { 9804658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return mUsageMonitor.getPremiumSmsPermission(packageName); 9814658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 9824658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 9834658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby /** 9844658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * Sets the premium SMS permission for the specified package and save the value asynchronously 9854658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * to persistent storage. 9864658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @param packageName the name of the package to set permission 9874658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @param permission one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER}, 9884658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or 9894658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW} 9904658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby */ 9914658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby public void setPremiumSmsPermission(String packageName, int permission) { 9924658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mUsageMonitor.setPremiumSmsPermission(packageName, permission); 9930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send the message along to the radio. 9970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 9980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker holds the SMS message to send 9990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract void sendSms(SmsTracker tracker); 10010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10038d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * Send the SMS via the PSTN network. 10048d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * 10058d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * @param tracker holds the Sms tracker ready to be sent 10068d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang */ 10078d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang protected abstract void sendSmsByPstn(SmsTracker tracker); 10088d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 10098d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang /** 10101260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * Retry the message along to the radio. 10111260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * 10121260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * @param tracker holds the SMS message to send 10131260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa */ 1014ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa public void sendRetrySms(SmsTracker tracker) { 1015ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa // re-routing to ImsSMSDispatcher 1016ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa if (mImsSMSDispatcher != null) { 1017ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa mImsSMSDispatcher.sendRetrySms(tracker); 1018ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } else { 1019ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa Rlog.e(TAG, mImsSMSDispatcher + " is null. Retry failed"); 1020ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1021ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 10221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 10231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** 10240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send the multi-part SMS based on multipart Sms tracker 10250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 10260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker holds the multipart Sms tracker ready to be sent 10270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void sendMultipartSms(SmsTracker tracker) { 10290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<String> parts; 10300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<PendingIntent> sentIntents; 10310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<PendingIntent> deliveryIntents; 10320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville HashMap<String, Object> map = tracker.mData; 10340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String destinationAddress = (String) map.get("destination"); 10360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String scAddress = (String) map.get("scaddress"); 10370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville parts = (ArrayList<String>) map.get("parts"); 10390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntents = (ArrayList<PendingIntent>) map.get("sentIntents"); 10400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville deliveryIntents = (ArrayList<PendingIntent>) map.get("deliveryIntents"); 10410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // check if in service 10430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int ss = mPhone.getServiceState().getState(); 10441260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // if sms over IMS is not supported on data and voice is not available... 10451260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) { 10460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0, count = parts.size(); i < count; i++) { 10470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent sentIntent = null; 10480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntents != null && sentIntents.size() > i) { 10490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent = sentIntents.get(i); 10500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleNotInService(ss, sentIntent); 10520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 10540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMultipartText(destinationAddress, scAddress, parts, sentIntents, deliveryIntents); 10570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Keeps track of an SMS that has been sent to the RIL, until it has 10610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * successfully been sent, or we're done trying. 10620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final class SmsTracker { 10640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // fields need to be public for derived SmsDispatchers 10650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final HashMap<String, Object> mData; 10660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int mRetryCount; 10671260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa public int mImsRetry; // nonzero indicates initial message was sent over Ims 10680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int mMessageRef; 10691260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String mFormat; 10700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final PendingIntent mSentIntent; 10720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final PendingIntent mDeliveryIntent; 10730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10742029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra public final PackageInfo mAppInfo; 10750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final String mDestAddress; 10760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10770217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun private long mTimestamp = System.currentTimeMillis(); 10780217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun private Uri mSentMessageUri; // Uri of persisted message if we wrote one 10790217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 10801260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa private SmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, 10811260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa PendingIntent deliveryIntent, PackageInfo appInfo, String destAddr, String format) { 10820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mData = data; 10830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mSentIntent = sentIntent; 10840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mDeliveryIntent = deliveryIntent; 10850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRetryCount = 0; 10862029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra mAppInfo = appInfo; 10870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mDestAddress = destAddr; 10881260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mFormat = format; 10891260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mImsRetry = 0; 10901260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mMessageRef = 0; 10910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Returns whether this tracker holds a multi-part SMS. 10950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the tracker holds a multi-part SMS; false otherwise 10960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10970d4bcdf379842af4b6304809156971e926f374f0Jake Hamby boolean isMultipart() { 10980217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun return mData.containsKey("parts"); 10990217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 11000217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 11010217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun /** 11020217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun * Persist this as a sent message 11030217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun */ 11040217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun void writeSentMessage(Context context) { 11050217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun String text = (String)mData.get("text"); 11060217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun if (text != null) { 11070217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun boolean deliveryReport = (mDeliveryIntent != null); 11080217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun // Using invalid threadId 0 here. When the message is inserted into the db, the 11090217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun // provider looks up the threadId based on the recipient(s). 11100217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun mSentMessageUri = Sms.addMessageToUri(context.getContentResolver(), 11110217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun Telephony.Sms.Sent.CONTENT_URI, 11120217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun mDestAddress, 11130217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun text /*body*/, 11140217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun null /*subject*/, 11150217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun mTimestamp /*date*/, 11160217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun true /*read*/, 11170217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun deliveryReport /*deliveryReport*/, 11180217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 0 /*threadId*/); 11190217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 11200217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 11210217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 11220217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun /** 11230217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun * Update the status of this message if we persisted it 11240217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun */ 11250217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun public void updateSentMessageStatus(Context context, int status) { 11260217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun if (mSentMessageUri != null) { 11270217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun // If we wrote this message in writeSentMessage, update it now 11280217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun ContentValues values = new ContentValues(1); 11290217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun values.put(Sms.STATUS, status); 11300217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun SqliteWrapper.update(context, context.getContentResolver(), 11310217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun mSentMessageUri, values, null, null); 11320217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 11330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1136ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected SmsTracker getSmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, 11371260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa PendingIntent deliveryIntent, String format) { 11381260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Get calling app package name via UID from Binder call 11391260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa PackageManager pm = mContext.getPackageManager(); 11401260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String[] packageNames = pm.getPackagesForUid(Binder.getCallingUid()); 11411260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 11421260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Get package info via packagemanager 11431260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa PackageInfo appInfo = null; 11441260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (packageNames != null && packageNames.length > 0) { 11451260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa try { 11461260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // XXX this is lossy- apps can share a UID 11471260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa appInfo = pm.getPackageInfo(packageNames[0], PackageManager.GET_SIGNATURES); 11481260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } catch (PackageManager.NameNotFoundException e) { 11491260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // error will be logged in sendRawPdu 11501260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 11511260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 11521260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Strip non-digits from destination phone number before checking for short codes 11531260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // and before displaying the number to the user if confirmation is required. 11541260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String destAddr = PhoneNumberUtils.extractNetworkPortion((String) data.get("destAddr")); 11551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa return new SmsTracker(data, sentIntent, deliveryIntent, appInfo, destAddr, format); 11561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 11571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1158ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr, 11591260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String text, SmsMessageBase.SubmitPduBase pdu) { 11601260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa HashMap<String, Object> map = new HashMap<String, Object>(); 11611260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("destAddr", destAddr); 11621260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("scAddr", scAddr); 11631260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("text", text); 11641260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("smsc", pdu.encodedScAddress); 11651260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("pdu", pdu.encodedMessage); 11661260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa return map; 11671260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 11681260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1169ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr, 11701260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu) { 11711260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa HashMap<String, Object> map = new HashMap<String, Object>(); 11721260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("destAddr", destAddr); 11731260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("scAddr", scAddr); 1174ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa map.put("destPort", destPort); 11751260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("data", data); 11761260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("smsc", pdu.encodedScAddress); 11771260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("pdu", pdu.encodedMessage); 11781260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa return map; 11791260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 11801260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 11810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 11820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Dialog listener for SMS confirmation dialog. 11830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 11840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final class ConfirmDialogListener 11854658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, 11864658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby CompoundButton.OnCheckedChangeListener { 11870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final SmsTracker mTracker; 11894658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby private Button mPositiveButton; 11904658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby private Button mNegativeButton; 11914658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby private boolean mRememberChoice; // default is unchecked 119278df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt private final TextView mRememberUndoInstruction; 11930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 119478df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ConfirmDialogListener(SmsTracker tracker, TextView textView) { 11950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mTracker = tracker; 119678df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction = textView; 11970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11994658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby void setPositiveButton(Button button) { 12004658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mPositiveButton = button; 12014658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 12024658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 12034658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby void setNegativeButton(Button button) { 12044658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mNegativeButton = button; 12054658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 12064658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 12070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 12080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void onClick(DialogInterface dialog, int which) { 12094658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // Always set the SMS permission so that Settings will show a permission setting 12104658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // for the app (it won't be shown until after the app tries to send to a short code). 12114658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER; 12124658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 12130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (which == DialogInterface.BUTTON_POSITIVE) { 1214ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "CONFIRM sending SMS"); 12152029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // XXX this is lossy- apps can have more than one signature 1216634a24f56f54b5d2911649288147c750b67c7ae4William Luh EventLog.writeEvent(EventLogTags.EXP_DET_SMS_SENT_BY_USER, 1217ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh mTracker.mAppInfo.applicationInfo == null ? 1218ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh -1 : mTracker.mAppInfo.applicationInfo.uid); 12190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_SEND_CONFIRMED_SMS, mTracker)); 12204658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (mRememberChoice) { 12214658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW; 12224658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 12230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (which == DialogInterface.BUTTON_NEGATIVE) { 1224ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "DENY sending SMS"); 12252029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // XXX this is lossy- apps can have more than one signature 1226634a24f56f54b5d2911649288147c750b67c7ae4William Luh EventLog.writeEvent(EventLogTags.EXP_DET_SMS_DENIED_BY_USER, 1227ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh mTracker.mAppInfo.applicationInfo == null ? 1228ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh -1 : mTracker.mAppInfo.applicationInfo.uid); 12290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_STOP_SENDING, mTracker)); 12304658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (mRememberChoice) { 12314658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW; 12324658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 12330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12344658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby setPremiumSmsPermission(mTracker.mAppInfo.packageName, newSmsPermission); 12350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 12380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void onCancel(DialogInterface dialog) { 1239ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "dialog dismissed: don't send SMS"); 12400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_STOP_SENDING, mTracker)); 12410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12424658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 12434658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby @Override 12444658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1245ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "remember this choice: " + isChecked); 12464658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mRememberChoice = isChecked; 12474658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (isChecked) { 12484658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mPositiveButton.setText(R.string.sms_short_code_confirm_always_allow); 12494658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mNegativeButton.setText(R.string.sms_short_code_confirm_never_allow); 125078df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt if (mRememberUndoInstruction != null) { 125178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction. 125278df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt setText(R.string.sms_short_code_remember_undo_instruction); 125378df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction.setPadding(0,0,0,32); 125478df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt } 12554658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } else { 12564658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mPositiveButton.setText(R.string.sms_short_code_confirm_allow); 12575d875796122cdd8a7004e8e3964b20b5c65a31a1Robert Greenwalt mNegativeButton.setText(R.string.sms_short_code_confirm_deny); 125878df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt if (mRememberUndoInstruction != null) { 125978df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction.setText(""); 126078df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction.setPadding(0,0,0,0); 126178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt } 12624658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 12634658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 12640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12651260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1266ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa public boolean isIms() { 1267ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa if (mImsSMSDispatcher != null) { 1268ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return mImsSMSDispatcher.isIms(); 1269ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } else { 1270ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa Rlog.e(TAG, mImsSMSDispatcher + " is null"); 1271ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return false; 1272ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1273ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 12741260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1275ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa public String getImsSmsFormat() { 1276ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa if (mImsSMSDispatcher != null) { 1277ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return mImsSMSDispatcher.getImsSmsFormat(); 1278ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } else { 1279ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa Rlog.e(TAG, mImsSMSDispatcher + " is null"); 1280ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return null; 1281ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1282ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 12830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville} 1284