SMSDispatcher.java revision 14bdfdca7a5412edf5fbdd6573e0f608233a5ae8
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; 18ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wangimport android.annotation.Nullable; 190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.Activity; 200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.AlertDialog; 210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.PendingIntent; 220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.PendingIntent.CanceledException; 230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.ContentResolver; 240217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.content.ContentValues; 250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Context; 260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.DialogInterface; 270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Intent; 280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.ApplicationInfo; 292029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condraimport android.content.pm.PackageInfo; 300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.PackageManager; 310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.res.Resources; 32ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwaltimport android.database.ContentObserver; 330217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.database.sqlite.SqliteWrapper; 340217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.net.Uri; 350825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult; 360825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Binder; 370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler; 380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message; 39f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawalimport android.os.Process; 408215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.os.RemoteException; 41f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawalimport android.os.UserHandle; 42ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwaltimport android.provider.Settings; 430217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.provider.Telephony; 440217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.provider.Telephony.Sms; 458215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.service.carrier.CarrierMessagingService; 468215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.service.carrier.ICarrierMessagingCallback; 478215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.service.carrier.ICarrierMessagingService; 488215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.telephony.CarrierMessagingServiceManager; 490825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.PhoneNumberUtils; 500d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.Rlog; 510825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.ServiceState; 520825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.TelephonyManager; 530825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.Html; 540825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.Spanned; 55b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.text.TextUtils; 562029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condraimport android.util.EventLog; 574658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.view.LayoutInflater; 584658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.view.View; 5978df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwaltimport android.view.ViewGroup; 600825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.WindowManager; 614658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.Button; 624658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.CheckBox; 634658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.CompoundButton; 644658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.TextView; 650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 660825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.R; 670825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; 68a9552aa6bf3ce12c75ad43165034d9a1233fb131Shishir Agrawalimport com.android.internal.telephony.uicc.UiccCard; 69c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport com.android.internal.telephony.uicc.UiccController; 700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 710825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList; 720825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.HashMap; 738d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport java.util.List; 740825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Random; 75c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport java.util.concurrent.atomic.AtomicBoolean; 760d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.util.concurrent.atomic.AtomicInteger; 770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 780825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE; 790825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_GENERIC_FAILURE; 800825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_LIMIT_EXCEEDED; 810825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_NO_SERVICE; 820825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_NULL_PDU; 830825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.telephony.SmsManager.RESULT_ERROR_RADIO_OFF; 840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 850825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic abstract class SMSDispatcher extends Handler { 86cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville static final String TAG = "SMSDispatcher"; // accessed from inner class 87cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville static final boolean DBG = false; 880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String SEND_NEXT_MSG_EXTRA = "SendNextMsg"; 890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 90ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private static final int PREMIUM_RULE_USE_SIM = 1; 91ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private static final int PREMIUM_RULE_USE_NETWORK = 2; 92ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private static final int PREMIUM_RULE_USE_BOTH = 3; 93ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private final AtomicInteger mPremiumSmsRule = new AtomicInteger(PREMIUM_RULE_USE_SIM); 94ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private final SettingsObserver mSettingsObserver; 95ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** SMS send complete. */ 970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final int EVENT_SEND_SMS_COMPLETE = 2; 980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Retry sending a previously failed SMS message */ 1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_SEND_RETRY = 3; 1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Confirmation required for sending a large number of messages. */ 1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_SEND_LIMIT_REACHED_CONFIRMATION = 4; 1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Send the user confirmed SMS */ 1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville static final int EVENT_SEND_CONFIRMED_SMS = 5; // accessed from inner class 1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Don't send SMS (user did not confirm). */ 1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville static final int EVENT_STOP_SENDING = 7; // accessed from inner class 1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Confirmation required for third-party apps sending to an SMS short code. */ 1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE = 8; 1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Confirmation required for third-party apps sending to an SMS short code. */ 1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE = 9; 1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1170d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** Handle status report from {@code CdmaInboundSmsHandler}. */ 1180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby protected static final int EVENT_HANDLE_STATUS_REPORT = 10; 1190d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 1201260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** Radio is ON */ 1211260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_RADIO_ON = 11; 1221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** IMS registration/SMS format changed */ 1241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_IMS_STATE_CHANGED = 12; 1251260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1261260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** Callback from RIL_REQUEST_IMS_REGISTRATION_STATE */ 1271260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_IMS_STATE_DONE = 13; 1281260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1291260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // other 1301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_NEW_ICC_SMS = 14; 1311260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected static final int EVENT_ICC_CHANGED = 15; 1321260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1331a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu protected Phone mPhone; 1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected final Context mContext; 1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected final ContentResolver mResolver; 13622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville protected final CommandsInterface mCi; 1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected final TelephonyManager mTelephonyManager; 1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Maximum number of times to retry sending a failed SMS. */ 1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int MAX_SEND_RETRIES = 3; 1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Delay before next send attempt on a failed SMS, in milliseconds. */ 1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int SEND_RETRY_DELAY = 2000; 1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** single part SMS */ 1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int SINGLE_PART_SMS = 1; 1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Message sending queue limit */ 1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int MO_MSG_QUEUE_LIMIT = 5; 1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Message reference for a CONCATENATED_8_BIT_REFERENCE or 1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * CONCATENATED_16_BIT_REFERENCE message set. Should be 1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * incremented for each set of concatenated messages. 1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Static field shared by all dispatcher objects. 1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static int sConcatenatedRef = new Random().nextInt(256); 1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Outgoing message counter. Shared by all dispatchers. */ 1571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa private SmsUsageMonitor mUsageMonitor; 1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 159ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa private ImsSMSDispatcher mImsSMSDispatcher; 160ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa 1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Number of outgoing SmsTrackers waiting for user confirmation. */ 1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private int mPendingTrackerCount; 1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* Flags indicating whether the current device allows sms service */ 1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected boolean mSmsCapable = true; 1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected boolean mSmsSendDisabled; 1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static int getNextConcatenatedRef() { 1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sConcatenatedRef += 1; 1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return sConcatenatedRef; 1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Create a new SMS dispatcher. 1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param phone the Phone to use 1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param usageMonitor the SmsUsageMonitor to use 1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 1781a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu protected SMSDispatcher(Phone phone, SmsUsageMonitor usageMonitor, 179ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa ImsSMSDispatcher imsSMSDispatcher) { 1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhone = phone; 181ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa mImsSMSDispatcher = imsSMSDispatcher; 1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mContext = phone.getContext(); 1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mResolver = mContext.getContentResolver(); 18422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville mCi = phone.mCi; 1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mUsageMonitor = usageMonitor; 1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 187ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mSettingsObserver = new SettingsObserver(this, mPremiumSmsRule, mContext); 188ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor( 189ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt Settings.Global.SMS_SHORT_CODE_RULE), false, mSettingsObserver); 1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mSmsCapable = mContext.getResources().getBoolean( 1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville com.android.internal.R.bool.config_sms_capable); 193e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu mSmsSendDisabled = !mTelephonyManager.getSmsSendCapableForPhone( 194e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu mPhone.getPhoneId(), mSmsCapable); 195ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "SMSDispatcher: ctor mSmsCapable=" + mSmsCapable + " format=" + getFormat() 1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville + " mSmsSendDisabled=" + mSmsSendDisabled); 1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 199ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt /** 200ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt * Observe the secure setting for updated premium sms determination rules 201ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt */ 202ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private static class SettingsObserver extends ContentObserver { 203ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private final AtomicInteger mPremiumSmsRule; 204ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt private final Context mContext; 205ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt SettingsObserver(Handler handler, AtomicInteger premiumSmsRule, Context context) { 206ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt super(handler); 207ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mPremiumSmsRule = premiumSmsRule; 208ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mContext = context; 209ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt onChange(false); // load initial value; 210ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 211ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 212ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt @Override 213ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt public void onChange(boolean selfChange) { 214ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt mPremiumSmsRule.set(Settings.Global.getInt(mContext.getContentResolver(), 215ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt Settings.Global.SMS_SHORT_CODE_RULE, PREMIUM_RULE_USE_SIM)); 216ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 217ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 218ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 2191a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu protected void updatePhoneObject(Phone phone) { 2201260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mPhone = phone; 2211260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mUsageMonitor = phone.mSmsUsageMonitor; 2221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa Rlog.d(TAG, "Active phone changed to " + mPhone.getPhoneName() ); 2231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 2241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Unregister for incoming SMS events. */ 2260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby public void dispose() { 2270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); 2280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The format of the message PDU in the associated broadcast intent. 2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * This will be either "3gpp" for GSM/UMTS/LTE messages in 3GPP format 2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or "3gpp2" for CDMA/LTE messages in 3GPP2 format. 2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Note: All applications which handle incoming SMS messages by processing the 2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * SMS_RECEIVED_ACTION broadcast intent MUST pass the "format" extra from the intent 2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * into the new methods in {@link android.telephony.SmsMessage} which take an 2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * extra format parameter. This is required in order to correctly decode the PDU on 2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * devices which require support for both 3GPP and 3GPP2 formats at the same time, 2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * such as CDMA/LTE devices and GSM/CDMA world phones. 2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return the format of the message PDU 2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract String getFormat(); 2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 2470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Pass the Message object to subclass to handle. Currently used to pass CDMA status reports 2480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * from {@link com.android.internal.telephony.cdma.CdmaInboundSmsHandler}. 2490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @param o the SmsMessage containing the status report 2500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 2510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby protected void handleStatusReport(Object o) { 2520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.d(TAG, "handleStatusReport() called with no subclass."); 2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* TODO: Need to figure out how to keep track of status report routing in a 2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * persistent manner. If the phone process restarts (reboot or crash), 2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * we will lose this list and any status reports that come in after 2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * will be dropped. 2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** Sent messages awaiting a delivery status report. */ 2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected final ArrayList<SmsTracker> deliveryPendingList = new ArrayList<SmsTracker>(); 2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Handles events coming from the phone stack. Overridden from handler. 2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param msg the message to handle 2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void handleMessage(Message msg) { 2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch (msg.what) { 2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_SMS_COMPLETE: 2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // An outbound SMS has been successfully transferred, or failed. 2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleSendComplete((AsyncResult) msg.obj); 2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_RETRY: 2771260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa Rlog.d(TAG, "SMS retry.."); 2781260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa sendRetrySms((SmsTracker) msg.obj); 2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_LIMIT_REACHED_CONFIRMATION: 2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleReachSentLimit((SmsTracker)(msg.obj)); 2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE: 2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleConfirmShortCode(false, (SmsTracker)(msg.obj)); 2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE: 2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleConfirmShortCode(true, (SmsTracker)(msg.obj)); 2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_SEND_CONFIRMED_SMS: 2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville { 2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsTracker tracker = (SmsTracker) msg.obj; 2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (tracker.isMultipart()) { 2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMultipartSms(tracker); 2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 2996c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying if (mPendingTrackerCount > 1) { 3006c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying tracker.mExpectMore = true; 3016c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying } else { 3026c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying tracker.mExpectMore = false; 3036c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying } 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; 313c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_LIMIT_EXCEEDED, 0/*errorCode*/); 3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPendingTrackerCount--; 3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby case EVENT_HANDLE_STATUS_REPORT: 3190d4bcdf379842af4b6304809156971e926f374f0Jake Hamby handleStatusReport(msg.obj); 3200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby break; 3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3220d4bcdf379842af4b6304809156971e926f374f0Jake Hamby default: 3230d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.e(TAG, "handleMessage() ignoring message of unexpected type " + msg.what); 3240d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 325b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby } 326b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby 327b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby /** 3288215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Use the carrier messaging service to send a data or text SMS. 3298215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 3308215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected abstract class SmsSender extends CarrierMessagingServiceManager { 3318215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected final SmsTracker mTracker; 3328215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang // Initialized in sendSmsByCarrierApp 3338215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected volatile SmsSenderCallback mSenderCallback; 3348215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 3358215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected SmsSender(SmsTracker tracker) { 3368215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mTracker = tracker; 3378215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3388215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 3398215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void sendSmsByCarrierApp(String carrierPackageName, 3408215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang SmsSenderCallback senderCallback) { 3418215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback = senderCallback; 3428215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (!bindToCarrierMessagingService(mContext, carrierPackageName)) { 3438215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "bindService() for carrier messaging service failed"); 3448215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendSmsComplete( 3458215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 3468215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 0 /* messageRef */); 3478215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } else { 3488215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "bindService() for carrier messaging service succeeded"); 3498215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3508215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3518215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3528215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 353ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang private static int getSendSmsFlag(@Nullable PendingIntent deliveryIntent) { 354ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang if (deliveryIntent == null) { 355ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang return 0; 356ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang } 357ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang return CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS; 358ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang } 359ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang 3608215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 3618215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Use the carrier messaging service to send a text SMS. 3628215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 3638215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected final class TextSmsSender extends SmsSender { 3648215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public TextSmsSender(SmsTracker tracker) { 3658215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang super(tracker); 3668215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3678215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 3688215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 3698215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected void onServiceReady(ICarrierMessagingService carrierMessagingService) { 3705d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan HashMap<String, Object> map = mTracker.getData(); 3718215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang String text = (String) map.get("text"); 3728215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 3738215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (text != null) { 3748215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang try { 3758215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang carrierMessagingService.sendTextSms(text, getSubId(), 376ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang mTracker.mDestAddress, getSendSmsFlag(mTracker.mDeliveryIntent), 377ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang mSenderCallback); 3788215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } catch (RemoteException e) { 3798215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Exception sending the SMS: " + e); 3808215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendSmsComplete( 3818215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 3828215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 0 /* messageRef */); 3838215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3848215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } else { 3858215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendSmsComplete( 3868215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 3878215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 0 /* messageRef */); 3888215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3898215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3908215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3918215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 3928215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 3938215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Use the carrier messaging service to send a data SMS. 3948215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 3958215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected final class DataSmsSender extends SmsSender { 3968215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public DataSmsSender(SmsTracker tracker) { 3978215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang super(tracker); 3988215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 3998215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4008215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 4018215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected void onServiceReady(ICarrierMessagingService carrierMessagingService) { 4025d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan HashMap<String, Object> map = mTracker.getData(); 4038215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang byte[] data = (byte[]) map.get("data"); 4048215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang int destPort = (int) map.get("destPort"); 4058215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4068215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (data != null) { 4078215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang try { 4088215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang carrierMessagingService.sendDataSms(data, getSubId(), 409ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang mTracker.mDestAddress, destPort, 410ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang getSendSmsFlag(mTracker.mDeliveryIntent), mSenderCallback); 4118215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } catch (RemoteException e) { 4128215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Exception sending the SMS: " + e); 4138215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendSmsComplete( 4148215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 4158215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 0 /* messageRef */); 4168215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4178215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } else { 4188215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendSmsComplete( 4198215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 4208215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 0 /* messageRef */); 4218215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4228215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4238215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4248215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4258215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 4268215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Callback for TextSmsSender and DataSmsSender from the carrier messaging service. 4278215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Once the result is ready, the carrier messaging service connection is disposed. 4288215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 4298215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected final class SmsSenderCallback extends ICarrierMessagingCallback.Stub { 4308215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private final SmsSender mSmsSender; 4318215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4328215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public SmsSenderCallback(SmsSender smsSender) { 4338215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSmsSender = smsSender; 4348215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4358215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4368215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 4378215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * This method should be called only once. 4388215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 4398215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 4408215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onSendSmsComplete(int result, int messageRef) { 441f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal checkCallerIsPhoneOrCarrierApp(); 442f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal final long identity = Binder.clearCallingIdentity(); 443f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal try { 444f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal mSmsSender.disposeConnection(mContext); 445f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal processSendSmsResponse(mSmsSender.mTracker, result, messageRef); 446f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal } finally { 447f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal Binder.restoreCallingIdentity(identity); 448f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal } 4498215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4508215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4518215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 4528215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onSendMultipartSmsComplete(int result, int[] messageRefs) { 4538215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onSendMultipartSmsComplete call with result: " + result); 4548215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4558215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4568215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 4578215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onFilterComplete(boolean keepMessage) { 4588215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onFilterComplete call with result: " + keepMessage); 4598215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4608215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4618215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 4628215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onSendMmsComplete(int result, byte[] sendConfPdu) { 4638215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onSendMmsComplete call with result: " + result); 4648215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4658215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4668215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 4678215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onDownloadMmsComplete(int result) { 4688215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onDownloadMmsComplete call with result: " + result); 4698215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4708215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4718215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4728215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private void processSendSmsResponse(SmsTracker tracker, int result, int messageRef) { 4738215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (tracker == null) { 4748215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "processSendSmsResponse: null tracker"); 4758215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang return; 4768215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 4778215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4788215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang SmsResponse smsResponse = new SmsResponse( 4798215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang messageRef, null /* ackPdu */, -1 /* unknown error code */); 4808215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 4818215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang switch (result) { 4828215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang case CarrierMessagingService.SEND_STATUS_OK: 4838215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "Sending SMS by IP succeeded."); 4848215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE, 4858215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang new AsyncResult(tracker, 4868215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang smsResponse, 4878215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang null /* exception*/ ))); 4888215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang break; 4898215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang case CarrierMessagingService.SEND_STATUS_ERROR: 4908215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "Sending SMS by IP failed."); 4918215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE, 4928215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang new AsyncResult(tracker, smsResponse, 4938215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang new CommandException(CommandException.Error.GENERIC_FAILURE)))); 4948215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang break; 4958215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang case CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK: 4968215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "Sending SMS by IP failed. Retry on carrier network."); 4978215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang sendSubmitPdu(tracker); 4988215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang break; 4998215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang default: 5008215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "Unknown result " + result + " Retry on carrier network."); 5018215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang sendSubmitPdu(tracker); 5028215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5038215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5048215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5058215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 5068215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Use the carrier messaging service to send a multipart text SMS. 5078215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 5088215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private final class MultipartSmsSender extends CarrierMessagingServiceManager { 5098215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private final List<String> mParts; 5108215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public final SmsTracker[] mTrackers; 5118215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang // Initialized in sendSmsByCarrierApp 5128215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private volatile MultipartSmsSenderCallback mSenderCallback; 5138215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5148215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang MultipartSmsSender(ArrayList<String> parts, SmsTracker[] trackers) { 5158215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mParts = parts; 5168215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mTrackers = trackers; 5178215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5188215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5198215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang void sendSmsByCarrierApp(String carrierPackageName, 5208215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang MultipartSmsSenderCallback senderCallback) { 5218215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback = senderCallback; 5228215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (!bindToCarrierMessagingService(mContext, carrierPackageName)) { 5238215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "bindService() for carrier messaging service failed"); 5248215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendMultipartSmsComplete( 5258215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 5268215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang null /* smsResponse */); 5278215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } else { 5288215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "bindService() for carrier messaging service succeeded"); 5298215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5308215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5318215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5328215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 5338215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected void onServiceReady(ICarrierMessagingService carrierMessagingService) { 5348215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang try { 5358215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang carrierMessagingService.sendMultipartTextSms( 536ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang mParts, getSubId(), mTrackers[0].mDestAddress, 537ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang getSendSmsFlag(mTrackers[0].mDeliveryIntent), mSenderCallback); 5388215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } catch (RemoteException e) { 5398215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Exception sending the SMS: " + e); 5408215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSenderCallback.onSendMultipartSmsComplete( 5418215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 5428215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang null /* smsResponse */); 5438215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5448215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5458215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5468215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5478215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 5488215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Callback for MultipartSmsSender from the carrier messaging service. 5498215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Once the result is ready, the carrier messaging service connection is disposed. 5508215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 5518215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private final class MultipartSmsSenderCallback extends ICarrierMessagingCallback.Stub { 5528215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang private final MultipartSmsSender mSmsSender; 5538215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5548215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang MultipartSmsSenderCallback(MultipartSmsSender smsSender) { 5558215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSmsSender = smsSender; 5568215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5578215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5588215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 5598215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onSendSmsComplete(int result, int messageRef) { 5608215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onSendSmsComplete call with result: " + result); 5618215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5628215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5638215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 5648215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * This method should be called only once. 5658215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 5668215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 5678215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onSendMultipartSmsComplete(int result, int[] messageRefs) { 5688215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mSmsSender.disposeConnection(mContext); 5698215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5708215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (mSmsSender.mTrackers == null) { 5718215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onSendMultipartSmsComplete call with null trackers."); 5728215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang return; 5738215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5748215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 575f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal checkCallerIsPhoneOrCarrierApp(); 576f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal final long identity = Binder.clearCallingIdentity(); 577f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal try { 578f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal for (int i = 0; i < mSmsSender.mTrackers.length; i++) { 579f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal int messageRef = 0; 580f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal if (messageRefs != null && messageRefs.length > i) { 581f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal messageRef = messageRefs[i]; 582f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal } 583f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal processSendSmsResponse(mSmsSender.mTrackers[i], result, messageRef); 5848215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 585f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal } finally { 586f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal Binder.restoreCallingIdentity(identity); 5878215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5888215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5898215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5908215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 5918215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onFilterComplete(boolean keepMessage) { 5928215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onFilterComplete call with result: " + keepMessage); 5938215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5948215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 5958215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 5968215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onSendMmsComplete(int result, byte[] sendConfPdu) { 5978215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onSendMmsComplete call with result: " + result); 5988215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 5998215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 6008215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang @Override 6018215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang public void onDownloadMmsComplete(int result) { 6028215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Unexpected onDownloadMmsComplete call with result: " + result); 6038215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 6048215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 6058215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 6068215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 6078215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Send an SMS PDU. Usually just calls {@link sendRawPdu}. 6088215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang */ 6098215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected abstract void sendSubmitPdu(SmsTracker tracker); 6108215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 6118215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang /** 6120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Called when SMS send completes. Broadcasts a sentIntent on success. 6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * On failure, either sets up retries or broadcasts a sentIntent with 6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the failure in the result code. 6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param ar AsyncResult passed into the message handler. ar.result should 6170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * an SmsResponse instance if send was successful. ar.userObj 6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * should be an SmsTracker instance. 6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void handleSendComplete(AsyncResult ar) { 6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsTracker tracker = (SmsTracker) ar.userObj; 6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent sentIntent = tracker.mSentIntent; 6230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 624454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks if (ar.result != null) { 6255a176f73dbb2bff2ca8b8f86af86a17be6863b87Wink Saville tracker.mMessageRef = ((SmsResponse)ar.result).mMessageRef; 626454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks } else { 627454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks Rlog.d(TAG, "SmsResponse was null"); 628454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks } 629454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks 6300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.exception == null) { 631cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville if (DBG) Rlog.d(TAG, "SMS send complete. Broadcasting intent: " + sentIntent); 6320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (tracker.mDeliveryIntent != null) { 6340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Expecting a status report. Add it to the list. 6350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville deliveryPendingList.add(tracker); 6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 637c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onSent(mContext); 6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 639cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville if (DBG) Rlog.d(TAG, "SMS send failed"); 6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int ss = mPhone.getServiceState().getState(); 6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6431260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if ( tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) { 6441260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // This is retry after failure over IMS but voice is not available. 6451260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Set retry to max allowed, so no retry is sent and 6461260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // cause RESULT_ERROR_GENERIC_FAILURE to be returned to app. 6471260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa tracker.mRetryCount = MAX_SEND_RETRIES; 6481260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 6491260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa Rlog.d(TAG, "handleSendComplete: Skipping retry: " 6501260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" isIms()="+isIms() 6511260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" mRetryCount="+tracker.mRetryCount 6521260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" mImsRetry="+tracker.mImsRetry 6531260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" mMessageRef="+tracker.mMessageRef 6541260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa +" SS= "+mPhone.getServiceState().getState()); 6551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 6561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 6571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // if sms over IMS is not supported on data and voice is not available... 6581260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) { 659c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, getNotInServiceError(ss), 0/*errorCode*/); 6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if ((((CommandException)(ar.exception)).getCommandError() 6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville == CommandException.Error.SMS_FAIL_RETRY) && 6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tracker.mRetryCount < MAX_SEND_RETRIES) { 6630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Retry after a delay if needed. 6640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TODO: According to TS 23.040, 9.2.3.6, we should resend 6650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // with the same TP-MR as the failed message, and 6660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TP-RD set to 1. However, we don't have a means of 6670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // knowing the MR for the failed message (EF_SMSstatus 6680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // may or may not have the MR corresponding to this 6690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // message, depending on the failure). Also, in some 6700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // implementations this retry is handled by the baseband. 6710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tracker.mRetryCount++; 6720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker); 6730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessageDelayed(retryMsg, SEND_RETRY_DELAY); 674c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } else { 675c99dab56e20222b28cbc6238645feac938f1c333Ye Wen int errorCode = 0; 676c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (ar.result != null) { 677c99dab56e20222b28cbc6238645feac938f1c333Ye Wen errorCode = ((SmsResponse)ar.result).mErrorCode; 678c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 6790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int error = RESULT_ERROR_GENERIC_FAILURE; 6800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (((CommandException)(ar.exception)).getCommandError() 6810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville == CommandException.Error.FDN_CHECK_FAILURE) { 6820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville error = RESULT_ERROR_FDN_CHECK_FAILURE; 6830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 684c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, error, errorCode); 6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Handles outbound message when the phone is not in service. 6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param ss Current service state. Valid values are: 6930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * OUT_OF_SERVICE 6940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * EMERGENCY_ONLY 6950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * POWER_OFF 6960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntent the PendingIntent to send the error to 6970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 6980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static void handleNotInService(int ss, PendingIntent sentIntent) { 6990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntent != null) { 7000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 7010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ss == ServiceState.STATE_POWER_OFF) { 7020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(RESULT_ERROR_RADIO_OFF); 7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 7040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent.send(RESULT_ERROR_NO_SERVICE); 7050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (CanceledException ex) {} 7070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 7090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 711c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param ss service state 712c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @return The result error based on input service state for not in service error 713c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 714c99dab56e20222b28cbc6238645feac938f1c333Ye Wen protected static int getNotInServiceError(int ss) { 715c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (ss == ServiceState.STATE_POWER_OFF) { 716c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return RESULT_ERROR_RADIO_OFF; 717c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 718c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return RESULT_ERROR_NO_SERVICE; 719c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 720c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 721c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 7220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a data based SMS to a specific application port. 7230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 7240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param destAddr the address to send the message to 7250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddr is the service center address or null to use 7260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the current default SMSC 7270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param destPort the port to deliver the message to 7280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param data the body of the message to send 7290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntent if not NULL this <code>PendingIntent</code> is 7300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is successfully sent, or failed. 7310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 7320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors:<br> 7330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 7340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code><br> 7350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code><br> 7360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code><br>. 7370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 7380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the extra "errorCode" containing a radio technology specific value, 7390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * generally only useful for troubleshooting.<br> 7400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 7410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 7420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 7430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 7440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is delivered to the recipient. The 7450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * raw pdu of the status report is in the extended data ("pdu"). 7460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 7470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract void sendData(String destAddr, String scAddr, int destPort, 7480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent); 7490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 7510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a text based SMS. 752b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param destAddr the address to send the message to 7530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddr is the service center address or null to use 7540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the current default SMSC 7550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param text the body of the message to send 7560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntent if not NULL this <code>PendingIntent</code> is 7570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is successfully sent, or failed. 7580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 7590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors:<br> 7600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 7610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code><br> 7620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code><br> 7630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code><br>. 7640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 7650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the extra "errorCode" containing a radio technology specific value, 7660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * generally only useful for troubleshooting.<br> 7670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 7680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 7690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 7700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 7710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is delivered to the recipient. The 772b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param messageUri optional URI of the message if it is already stored in the system 773b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param callingPkg the calling package name 774a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang * @param persistMessage whether to save the sent message into SMS DB for a 775a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang * non-default SMS app. 7760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 777b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen protected abstract void sendText(String destAddr, String scAddr, String text, 778b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri, 779a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang String callingPkg, boolean persistMessage); 7800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 7810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 78263418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * Inject an SMS PDU into the android platform. 78363418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * 78463418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * @param pdu is the byte array of pdu to be injected into android telephony layer 78563418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * @param format is the format of SMS pdu (3gpp or 3gpp2) 78663418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * @param receivedIntent if not NULL this <code>PendingIntent</code> is 78763418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * broadcast when the message is successfully received by the 78863418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * android telephony layer. This intent is broadcasted at 78963418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni * the same time an SMS received from radio is responded back. 79063418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni */ 79163418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni protected abstract void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent); 79263418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni 79363418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni /** 7943ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan * Calculate the number of septets needed to encode the message. This function should only be 7953ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan * called for individual segments of multipart message. 7960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 7970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param messageBody the message to encode 7980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param use7bitOnly ignore (but still count) illegal characters if true 7990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return TextEncodingDetails 8000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract TextEncodingDetails calculateLength(CharSequence messageBody, 8020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean use7bitOnly); 8030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 8050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send a multi-part text based SMS. 806b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param destAddr the address to send the message to 8070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param scAddr is the service center address or null to use 8080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the current default SMSC 8090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param parts an <code>ArrayList</code> of strings that, in order, 8100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * comprise the original message 8110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param sentIntents if not null, an <code>ArrayList</code> of 8120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>PendingIntent</code>s (one for each message part) that is 8130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the corresponding message part has been sent. 8140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 8150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors: 8160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code> 8170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code> 8180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code> 8190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code>. 8200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 8210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 8220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 8230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param deliveryIntents if not null, an <code>ArrayList</code> of 8240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>PendingIntent</code>s (one for each message part) that is 8250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the corresponding message part has been delivered 8260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * to the recipient. The raw pdu of the status report is in the 827b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param messageUri optional URI of the message if it is already stored in the system 828b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen * @param callingPkg the calling package name 829a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang * @param persistMessage whether to save the sent message into SMS DB for a 830a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang * non-default SMS app. 8310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 8320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void sendMultipartText(String destAddr, String scAddr, 8330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, 834a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg, 835a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang boolean persistMessage) { 8364bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final String fullMessageText = getMultipartMessageText(parts); 8370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int refNumber = getNextConcatenatedRef() & 0x00FF; 8380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int msgCount = parts.size(); 8390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int encoding = SmsConstants.ENCODING_UNKNOWN; 8400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount]; 8420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < msgCount; i++) { 8430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TextEncodingDetails details = calculateLength(parts.get(i), false); 8440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (encoding != details.codeUnitSize 8450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville && (encoding == SmsConstants.ENCODING_UNKNOWN 8460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville || encoding == SmsConstants.ENCODING_7BIT)) { 8470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encoding = details.codeUnitSize; 8480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville encodingForParts[i] = details; 8500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8528215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang SmsTracker[] trackers = new SmsTracker[msgCount]; 8538215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 854c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // States to track at the message level (for all parts) 855c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final AtomicInteger unsentPartCount = new AtomicInteger(msgCount); 856c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final AtomicBoolean anyPartFailed = new AtomicBoolean(false); 857c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 8580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < msgCount; i++) { 8590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); 8600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.refNumber = refNumber; 8610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.seqNumber = i + 1; // 1-based sequence 8620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.msgCount = msgCount; 8630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // TODO: We currently set this to true since our messaging app will never 8640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // send more than 255 parts (it converts the message to MMS well before that). 8650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // However, we should support 3rd party messaging apps that might need 16-bit 8660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // references 8670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Note: It's not sufficient to just flip this bit to true; it will have 8680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // ripple effects (several calculations assume 8-bit ref). 8690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville concatRef.isEightBits = true; 8700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SmsHeader smsHeader = new SmsHeader(); 8710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsHeader.concatRef = concatRef; 8720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Set the national language tables for 3GPP 7-bit encoding, if enabled. 8740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (encoding == SmsConstants.ENCODING_7BIT) { 8750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsHeader.languageTable = encodingForParts[i].languageTable; 8760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable; 8770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent sentIntent = null; 8800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntents != null && sentIntents.size() > i) { 8810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent = sentIntents.get(i); 8820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent deliveryIntent = null; 8850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (deliveryIntents != null && deliveryIntents.size() > i) { 8860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville deliveryIntent = deliveryIntents.get(i); 8870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 8880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 8898215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang trackers[i] = 8908215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang getNewSubmitPduTracker(destAddr, scAddr, parts.get(i), smsHeader, encoding, 8918215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang sentIntent, deliveryIntent, (i == (msgCount - 1)), 8928215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang unsentPartCount, anyPartFailed, messageUri, fullMessageText); 893a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang trackers[i].mPersistMessage = persistMessage; 8948215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 8958215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 8968215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (parts == null || trackers == null || trackers.length == 0 8978215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang || trackers[0] == null) { 8988215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Cannot send multipart text. parts=" + parts + " trackers=" + trackers); 8998215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang return; 9008215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 9018215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang 9028215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang String carrierPackage = getCarrierAppPackageName(); 9038215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (carrierPackage != null) { 9048215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.d(TAG, "Found carrier package."); 9058215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang MultipartSmsSender smsSender = new MultipartSmsSender(parts, trackers); 9068215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang smsSender.sendSmsByCarrierApp(carrierPackage, new MultipartSmsSenderCallback(smsSender)); 9078215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } else { 9088215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.v(TAG, "No carrier package."); 9098215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang for (SmsTracker tracker : trackers) { 9108215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang if (tracker != null) { 9118215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang sendSubmitPdu(tracker); 9128215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } else { 9138215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang Rlog.e(TAG, "Null tracker."); 9148215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 9158215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang } 9160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9208215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Create a new SubmitPdu and return the SMS tracker. 9210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 9228215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected abstract SmsTracker getNewSubmitPduTracker(String destinationAddress, String scAddress, 9230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String message, SmsHeader smsHeader, int encoding, 924c99dab56e20222b28cbc6238645feac938f1c333Ye Wen PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart, 9254bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, 9264bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen String fullMessageText); 9270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 9298215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang * Send an SMS 9301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * @param tracker will contain: 9311260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -smsc the SMSC to send the message through, or NULL for the 9320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * default SMSC 9331260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -pdu the raw PDU to send 9341260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -sentIntent if not NULL this <code>Intent</code> is 9350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is successfully sent, or failed. 9360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The result code will be <code>Activity.RESULT_OK<code> for success, 9370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * or one of these errors: 9380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_GENERIC_FAILURE</code> 9390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_RADIO_OFF</code> 9400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NULL_PDU</code> 9410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <code>RESULT_ERROR_NO_SERVICE</code>. 9420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The per-application based SMS control checks sentIntent. If sentIntent 9430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is NULL the caller will be checked against all unknown applications, 9440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * which cause smaller number of SMS to be sent in checking period. 9451260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -deliveryIntent if not NULL this <code>Intent</code> is 9460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * broadcast when the message is delivered to the recipient. The 9470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * raw pdu of the status report is in the extended data ("pdu"). 9481260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * -param destAddr the destination phone number (for short code confirmation) 9490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 9501260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa protected void sendRawPdu(SmsTracker tracker) { 9515d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan HashMap map = tracker.getData(); 9521260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa byte pdu[] = (byte[]) map.get("pdu"); 9531260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 9540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mSmsSendDisabled) { 955c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Device does not support sending sms."); 956c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_NO_SERVICE, 0/*errorCode*/); 9570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 9580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (pdu == null) { 961c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Empty PDU"); 962c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_NULL_PDU, 0/*errorCode*/); 9630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 9640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Get calling app package name via UID from Binder call 9670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PackageManager pm = mContext.getPackageManager(); 9680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String[] packageNames = pm.getPackagesForUid(Binder.getCallingUid()); 9690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (packageNames == null || packageNames.length == 0) { 9710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Refuse to send SMS if we can't get the calling package name. 972ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get calling app package name: refusing to send SMS"); 973c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/); 9740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 9750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9772029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // Get package info via packagemanager 9780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby PackageInfo appInfo; 9792029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra try { 9802029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // XXX this is lossy- apps can share a UID 9812029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra appInfo = pm.getPackageInfo(packageNames[0], PackageManager.GET_SIGNATURES); 9822029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra } catch (PackageManager.NameNotFoundException e) { 983ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "Can't get calling app package info: refusing to send SMS"); 984c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/); 9852029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra return; 9862029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra } 9870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 9880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // checkDestination() returns true if the destination is not a premium short code or the 9890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // sending app is approved to send to short codes. Otherwise, a message is sent to our 9900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // handler with the SmsTracker to request user confirmation before sending. 9910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (checkDestination(tracker)) { 9920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // check for excessive outgoing SMS usage by this app 9932029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra if (!mUsageMonitor.check(appInfo.packageName, SINGLE_PART_SMS)) { 9940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, tracker)); 9950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 9960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 9970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 998a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal sendSms(tracker); 9990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Check if destination is a potential premium short code and sender is not pre-approved to 10040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * send to short codes. 10050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 10060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker the tracker for the SMS to send 10070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the destination is approved; false if user confirmation event was sent 10080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean checkDestination(SmsTracker tracker) { 1010d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan int rule = mPremiumSmsRule.get(); 1011d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan int smsCategory = SmsUsageMonitor.CATEGORY_NOT_SHORT_CODE; 1012d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan if (rule == PREMIUM_RULE_USE_SIM || rule == PREMIUM_RULE_USE_BOTH) { 1013d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan String simCountryIso = mTelephonyManager.getSimCountryIso(); 1014d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan if (simCountryIso == null || simCountryIso.length() != 2) { 1015d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan Rlog.e(TAG, "Can't get SIM country Iso: trying network country Iso"); 1016d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan simCountryIso = mTelephonyManager.getNetworkCountryIso(); 1017ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt } 1018ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt 1019d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan smsCategory = mUsageMonitor.checkDestination(tracker.mDestAddress, simCountryIso); 1020d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan } 1021d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan if (rule == PREMIUM_RULE_USE_NETWORK || rule == PREMIUM_RULE_USE_BOTH) { 1022d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan String networkCountryIso = mTelephonyManager.getNetworkCountryIso(); 1023d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan if (networkCountryIso == null || networkCountryIso.length() != 2) { 1024d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan Rlog.e(TAG, "Can't get Network country Iso: trying SIM country Iso"); 1025d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan networkCountryIso = mTelephonyManager.getSimCountryIso(); 10260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1028d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan smsCategory = SmsUsageMonitor.mergeShortCodeCategories(smsCategory, 1029d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan mUsageMonitor.checkDestination(tracker.mDestAddress, networkCountryIso)); 1030d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan } 10314658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 1032d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan if (smsCategory == SmsUsageMonitor.CATEGORY_NOT_SHORT_CODE 1033d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan || smsCategory == SmsUsageMonitor.CATEGORY_FREE_SHORT_CODE 1034d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan || smsCategory == SmsUsageMonitor.CATEGORY_STANDARD_SHORT_CODE) { 1035d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan return true; // not a premium short code 1036d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan } 10370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1038d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan // Wait for user confirmation unless the user has set permission to always allow/deny 1039d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan int premiumSmsPermission = mUsageMonitor.getPremiumSmsPermission( 1040d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan tracker.mAppInfo.packageName); 1041d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan if (premiumSmsPermission == SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) { 1042d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan // First time trying to send to premium SMS. 1043d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan premiumSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER; 1044d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan } 1045d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan 1046d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan switch (premiumSmsPermission) { 1047d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW: 1048d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan Rlog.d(TAG, "User approved this app to send to premium SMS"); 1049d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan return true; 1050d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan 1051d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW: 1052d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan Rlog.w(TAG, "User denied this app from sending to premium SMS"); 1053d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan sendMessage(obtainMessage(EVENT_STOP_SENDING, tracker)); 1054d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan return false; // reject this message 1055d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan 1056d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER: 1057d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan default: 1058d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan int event; 1059d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan if (smsCategory == SmsUsageMonitor.CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE) { 1060d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan event = EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE; 1061d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan } else { 1062d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan event = EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE; 1063d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan } 1064d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan sendMessage(obtainMessage(event, tracker)); 1065d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan return false; // wait for user confirmation 10660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Deny sending an SMS if the outgoing queue limit is reached. Used when the message 10710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * must be confirmed by the user due to excessive usage or potential premium SMS detected. 10720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker the SmsTracker for the message to send 10730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the message was denied; false to continue with send confirmation 10740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean denyIfQueueLimitReached(SmsTracker tracker) { 10760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mPendingTrackerCount >= MO_MSG_QUEUE_LIMIT) { 10770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Deny sending message when the queue limit is reached. 1078c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Denied because queue limit reached"); 1079c99dab56e20222b28cbc6238645feac938f1c333Ye Wen tracker.onFailed(mContext, RESULT_ERROR_LIMIT_EXCEEDED, 0/*errorCode*/); 10800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return true; 10810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPendingTrackerCount++; 10830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return false; 10840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 10850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 10860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 10870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Returns the label for the specified app package name. 10880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param appPackage the package name of the app requesting to send an SMS 10890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return the label for the specified app, or the package name if getApplicationInfo() fails 10900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 10910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private CharSequence getAppLabel(String appPackage) { 10920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PackageManager pm = mContext.getPackageManager(); 10930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 10940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ApplicationInfo appInfo = pm.getApplicationInfo(appPackage, 0); 10950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return appInfo.loadLabel(pm); 10960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (PackageManager.NameNotFoundException e) { 1097ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(TAG, "PackageManager Name Not Found for package " + appPackage); 10980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return appPackage; // fall back to package name if we can't get app label 10990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 11030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Post an alert when SMS needs confirmation due to excessive usage. 11040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker an SmsTracker for the current message. 11050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 11060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void handleReachSentLimit(SmsTracker tracker) { 11070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (denyIfQueueLimitReached(tracker)) { 11080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; // queue limit reached; error was returned to caller 11090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11112029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra CharSequence appLabel = getAppLabel(tracker.mAppInfo.packageName); 11120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Resources r = Resources.getSystem(); 11130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Spanned messageText = Html.fromHtml(r.getString(R.string.sms_control_message, appLabel)); 11140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 111578df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ConfirmDialogListener listener = new ConfirmDialogListener(tracker, null); 11160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AlertDialog d = new AlertDialog.Builder(mContext) 11180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setTitle(R.string.sms_control_title) 11190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setIcon(R.drawable.stat_sys_warning) 11200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setMessage(messageText) 11210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setPositiveButton(r.getString(R.string.sms_control_yes), listener) 11220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setNegativeButton(r.getString(R.string.sms_control_no), listener) 11230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setOnCancelListener(listener) 11240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .create(); 11250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 11270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.show(); 11280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 11310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Post an alert for user confirmation when sending to a potential short code. 11320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param isPremium true if the destination is known to be a premium short code 11330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker the SmsTracker for the current message. 11340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 11350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected void handleConfirmShortCode(boolean isPremium, SmsTracker tracker) { 11360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (denyIfQueueLimitReached(tracker)) { 11370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; // queue limit reached; error was returned to caller 11380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11404658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int detailsId; 11410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (isPremium) { 11424658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby detailsId = R.string.sms_premium_short_code_details; 11430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 11444658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby detailsId = R.string.sms_short_code_details; 11450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 11460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11472029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra CharSequence appLabel = getAppLabel(tracker.mAppInfo.packageName); 11480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Resources r = Resources.getSystem(); 11494658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby Spanned messageText = Html.fromHtml(r.getString(R.string.sms_short_code_confirm_message, 11504658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby appLabel, tracker.mDestAddress)); 11510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11524658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 11534658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby Context.LAYOUT_INFLATER_SERVICE); 11544658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby View layout = inflater.inflate(R.layout.sms_short_code_confirmation_dialog, null); 11554658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 115678df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ConfirmDialogListener listener = new ConfirmDialogListener(tracker, 115778df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt (TextView)layout.findViewById(R.id.sms_short_code_remember_undo_instruction)); 115878df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt 115978df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt 11604658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby TextView messageView = (TextView) layout.findViewById(R.id.sms_short_code_confirm_message); 11614658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby messageView.setText(messageText); 11624658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 116378df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ViewGroup detailsLayout = (ViewGroup) layout.findViewById( 11644658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby R.id.sms_short_code_detail_layout); 11654658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby TextView detailsView = (TextView) detailsLayout.findViewById( 11664658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby R.id.sms_short_code_detail_message); 11674658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby detailsView.setText(detailsId); 11684658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 11694658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby CheckBox rememberChoice = (CheckBox) layout.findViewById( 11704658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby R.id.sms_short_code_remember_choice_checkbox); 11714658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby rememberChoice.setOnCheckedChangeListener(listener); 11724658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 11730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AlertDialog d = new AlertDialog.Builder(mContext) 11744658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby .setView(layout) 11750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setPositiveButton(r.getString(R.string.sms_short_code_confirm_allow), listener) 11760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setNegativeButton(r.getString(R.string.sms_short_code_confirm_deny), listener) 11770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setOnCancelListener(listener) 11780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .create(); 11790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 11800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 11810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville d.show(); 11824658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 11834658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby listener.setPositiveButton(d.getButton(DialogInterface.BUTTON_POSITIVE)); 11844658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby listener.setNegativeButton(d.getButton(DialogInterface.BUTTON_NEGATIVE)); 11854658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 11864658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 11874658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby /** 11884658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * Returns the premium SMS permission for the specified package. If the package has never 11894658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * been seen before, the default {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER} 11904658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * will be returned. 11914658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @param packageName the name of the package to query permission 11924658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @return one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_UNKNOWN}, 11934658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER}, 11944658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or 11954658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW} 11964658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby */ 11974658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby public int getPremiumSmsPermission(String packageName) { 11984658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby return mUsageMonitor.getPremiumSmsPermission(packageName); 11994658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 12004658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 12014658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby /** 12024658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * Sets the premium SMS permission for the specified package and save the value asynchronously 12034658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * to persistent storage. 12044658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @param packageName the name of the package to set permission 12054658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * @param permission one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER}, 12064658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or 12074658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby * {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW} 12084658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby */ 12094658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby public void setPremiumSmsPermission(String packageName, int permission) { 12104658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mUsageMonitor.setPremiumSmsPermission(packageName, permission); 12110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 12140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send the message along to the radio. 12150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 12160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker holds the SMS message to send 12170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 12180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected abstract void sendSms(SmsTracker tracker); 12190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 12218d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * Send the SMS via the PSTN network. 12228d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * 12238d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang * @param tracker holds the Sms tracker ready to be sent 12248d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang */ 12258d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang protected abstract void sendSmsByPstn(SmsTracker tracker); 12268d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang 12278d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang /** 12281260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * Retry the message along to the radio. 12291260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * 12301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa * @param tracker holds the SMS message to send 12311260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa */ 1232ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa public void sendRetrySms(SmsTracker tracker) { 1233ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa // re-routing to ImsSMSDispatcher 1234ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa if (mImsSMSDispatcher != null) { 1235ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa mImsSMSDispatcher.sendRetrySms(tracker); 1236ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } else { 1237ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa Rlog.e(TAG, mImsSMSDispatcher + " is null. Retry failed"); 1238ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1239ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 12401260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 12411260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa /** 12420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Send the multi-part SMS based on multipart Sms tracker 12430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 12440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @param tracker holds the multipart Sms tracker ready to be sent 12450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 12460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void sendMultipartSms(SmsTracker tracker) { 12470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<String> parts; 12480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<PendingIntent> sentIntents; 12490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<PendingIntent> deliveryIntents; 12500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12515d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan HashMap<String, Object> map = tracker.getData(); 12520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String destinationAddress = (String) map.get("destination"); 12540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String scAddress = (String) map.get("scaddress"); 12550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville parts = (ArrayList<String>) map.get("parts"); 12570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntents = (ArrayList<PendingIntent>) map.get("sentIntents"); 12580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville deliveryIntents = (ArrayList<PendingIntent>) map.get("deliveryIntents"); 12590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // check if in service 12610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int ss = mPhone.getServiceState().getState(); 12621260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // if sms over IMS is not supported on data and voice is not available... 12631260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) { 12640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0, count = parts.size(); i < count; i++) { 12650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PendingIntent sentIntent = null; 12660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (sentIntents != null && sentIntents.size() > i) { 12670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sentIntent = sentIntents.get(i); 12680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville handleNotInService(ss, sentIntent); 12700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 12720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1274b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen sendMultipartText(destinationAddress, scAddress, parts, sentIntents, deliveryIntents, 1275a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang null/*messageUri*/, null/*callingPkg*/, tracker.mPersistMessage); 12760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 12770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 12790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Keeps track of an SMS that has been sent to the RIL, until it has 12800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * successfully been sent, or we're done trying. 12810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 12825d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan public static class SmsTracker { 12830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // fields need to be public for derived SmsDispatchers 12845d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan private final HashMap<String, Object> mData; 12850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int mRetryCount; 12861260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa public int mImsRetry; // nonzero indicates initial message was sent over Ims 12870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public int mMessageRef; 12886ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi public boolean mExpectMore; 12891260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String mFormat; 12900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final PendingIntent mSentIntent; 12920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final PendingIntent mDeliveryIntent; 12930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 12942029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra public final PackageInfo mAppInfo; 12950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public final String mDestAddress; 12960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 129778d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal public final SmsHeader mSmsHeader; 129878d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal 12990217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun private long mTimestamp = System.currentTimeMillis(); 1300c99dab56e20222b28cbc6238645feac938f1c333Ye Wen public Uri mMessageUri; // Uri of persisted message if we wrote one 1301c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1302c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // Reference to states of a multipart message that this part belongs to 1303c99dab56e20222b28cbc6238645feac938f1c333Ye Wen private AtomicInteger mUnsentPartCount; 1304c99dab56e20222b28cbc6238645feac938f1c333Ye Wen private AtomicBoolean mAnyPartFailed; 13054bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // The full message content of a single part message 13064bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // or a multipart message that this part belongs to 13074bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen private String mFullMessageText; 13084bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen 13094bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen private int mSubId; 13100217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 131152a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen // If this is a text message (instead of data message) 131252a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen private boolean mIsText; 131352a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen 1314a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang private boolean mPersistMessage; 1315a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang 13161260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa private SmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, 1317c99dab56e20222b28cbc6238645feac938f1c333Ye Wen PendingIntent deliveryIntent, PackageInfo appInfo, String destAddr, String format, 131878d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, 131952a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen SmsHeader smsHeader, boolean isExpectMore, String fullMessageText, int subId, 1320a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang boolean isText, boolean persistMessage) { 13210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mData = data; 13220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mSentIntent = sentIntent; 13230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mDeliveryIntent = deliveryIntent; 13240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRetryCount = 0; 13252029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra mAppInfo = appInfo; 13260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mDestAddress = destAddr; 13271260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mFormat = format; 13286ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi mExpectMore = isExpectMore; 13291260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mImsRetry = 0; 13301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa mMessageRef = 0; 1331c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mUnsentPartCount = unsentPartCount; 1332c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mAnyPartFailed = anyPartFailed; 1333c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mMessageUri = messageUri; 133478d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal mSmsHeader = smsHeader; 13354bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen mFullMessageText = fullMessageText; 13364bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen mSubId = subId; 133752a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen mIsText = isText; 1338a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang mPersistMessage = persistMessage; 13390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 13400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 13410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 13420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Returns whether this tracker holds a multi-part SMS. 13430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @return true if the tracker holds a multi-part SMS; false otherwise 13440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 13450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby boolean isMultipart() { 13460217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun return mData.containsKey("parts"); 13470217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 13480217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun 13495d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan public HashMap<String, Object> getData() { 13505d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan return mData; 13515d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan } 13525d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan 13530217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun /** 13540217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun * Update the status of this message if we persisted it 13550217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun */ 13560217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun public void updateSentMessageStatus(Context context, int status) { 1357c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mMessageUri != null) { 13580217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun // If we wrote this message in writeSentMessage, update it now 13590217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun ContentValues values = new ContentValues(1); 13600217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun values.put(Sms.STATUS, status); 13610217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun SqliteWrapper.update(context, context.getContentResolver(), 1362c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mMessageUri, values, null, null); 1363c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1364c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1365c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1366c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 13674bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * Set the final state of a message: FAILED or SENT 1368c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * 1369c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param context The Context 13704bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param messageType The final message type 1371c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param errorCode The error code 1372c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 13734bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen private void updateMessageState(Context context, int messageType, int errorCode) { 1374c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mMessageUri == null) { 1375c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return; 1376c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 13774bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final ContentValues values = new ContentValues(2); 13784bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.TYPE, messageType); 1379c99dab56e20222b28cbc6238645feac938f1c333Ye Wen values.put(Sms.ERROR_CODE, errorCode); 1380c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final long identity = Binder.clearCallingIdentity(); 1381c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 1382c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (SqliteWrapper.update(context, context.getContentResolver(), mMessageUri, values, 1383c99dab56e20222b28cbc6238645feac938f1c333Ye Wen null/*where*/, null/*selectionArgs*/) != 1) { 13844bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen Rlog.e(TAG, "Failed to move message to " + messageType); 1385c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1386c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } finally { 1387c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Binder.restoreCallingIdentity(identity); 1388c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1389c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1390c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1391c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 139252a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen * Persist a sent SMS if required: 139352a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen * 1. It is a text message 139452a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen * 2. SmsApplication tells us to persist: sent from apps that are not default-SMS app or 139552a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen * bluetooth 1396c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * 13974bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param context 13984bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param messageType The folder to store (FAILED or SENT) 13994bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param errorCode The current error code for this SMS or SMS part 14004bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @return The telephony provider URI if stored 1401c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 14024bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen private Uri persistSentMessageIfRequired(Context context, int messageType, int errorCode) { 1403a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang if (!mIsText || !mPersistMessage || 140452a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen !SmsApplication.shouldWriteMessageForPackage(mAppInfo.packageName, context)) { 14054bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen return null; 14064bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } 14074bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen Rlog.d(TAG, "Persist SMS into " 14084bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen + (messageType == Sms.MESSAGE_TYPE_FAILED ? "FAILED" : "SENT")); 14094bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final ContentValues values = new ContentValues(); 14104b09dff383ae7dfca595aeeea886a594a1947340Wink Saville values.put(Sms.SUBSCRIPTION_ID, mSubId); 14114bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.ADDRESS, mDestAddress); 14124bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.BODY, mFullMessageText); 14134bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.DATE, System.currentTimeMillis()); // milliseconds 14144bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.SEEN, 1); 14154bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.READ, 1); 14164bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final String creator = mAppInfo != null ? mAppInfo.packageName : null; 14174bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen if (!TextUtils.isEmpty(creator)) { 14184bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.CREATOR, creator); 14194bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } 14204bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen if (mDeliveryIntent != null) { 14214bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.STATUS, Telephony.Sms.STATUS_PENDING); 14224bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } 14234bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen if (errorCode != 0) { 14244bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen values.put(Sms.ERROR_CODE, errorCode); 1425c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1426c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final long identity = Binder.clearCallingIdentity(); 14274bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final ContentResolver resolver = context.getContentResolver(); 1428c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 14294bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final Uri uri = resolver.insert(Telephony.Sms.Sent.CONTENT_URI, values); 14304bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen if (uri != null && messageType == Sms.MESSAGE_TYPE_FAILED) { 14314bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // Since we can't persist a message directly into FAILED box, 14324bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // we have to update the column after we persist it into SENT box. 14334bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // The gap between the state change is tiny so I would not expect 14344bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // it to cause any serious problem 14354bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen // TODO: we should add a "failed" URI for this in SmsProvider? 14364bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen final ContentValues updateValues = new ContentValues(1); 14374bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen updateValues.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED); 14384bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen resolver.update(uri, updateValues, null/*where*/, null/*selectionArgs*/); 1439c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 14404bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen return uri; 14414bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } catch (Exception e) { 14424bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen Rlog.e(TAG, "writeOutboxMessage: Failed to persist outbox message", e); 14434bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen return null; 1444c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } finally { 1445c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Binder.restoreCallingIdentity(identity); 1446c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1447c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1448c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1449c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 14504bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * Persist or update an SMS depending on if we send a new message or a stored message 14514bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * 14524bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param context 14534bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param messageType The message folder for this SMS, FAILED or SENT 14544bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen * @param errorCode The current error code for this SMS or SMS part 14554bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen */ 14564bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen private void persistOrUpdateMessage(Context context, int messageType, int errorCode) { 14574bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen if (mMessageUri != null) { 14584bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen updateMessageState(context, messageType, errorCode); 14594bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } else { 14604bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen mMessageUri = persistSentMessageIfRequired(context, messageType, errorCode); 14614bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } 14624bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen } 14634bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen 14644bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen /** 1465c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * Handle a failure of a single part message or a part of a multipart message 1466c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * 1467c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param context The Context 1468c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param error The error to send back with 1469c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param errorCode 1470c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 1471c99dab56e20222b28cbc6238645feac938f1c333Ye Wen public void onFailed(Context context, int error, int errorCode) { 1472c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mAnyPartFailed != null) { 1473c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mAnyPartFailed.set(true); 1474c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1475c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // is single part or last part of multipart message 1476c99dab56e20222b28cbc6238645feac938f1c333Ye Wen boolean isSinglePartOrLastPart = true; 1477c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mUnsentPartCount != null) { 1478c99dab56e20222b28cbc6238645feac938f1c333Ye Wen isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0; 1479c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1480c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (isSinglePartOrLastPart) { 14814bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen persistOrUpdateMessage(context, Sms.MESSAGE_TYPE_FAILED, errorCode); 1482c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1483c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mSentIntent != null) { 1484c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 1485fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen // Extra information to send with the sent intent 1486fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen Intent fillIn = new Intent(); 1487fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen if (mMessageUri != null) { 1488fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen // Pass this to SMS apps so that they know where it is stored 1489fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen fillIn.putExtra("uri", mMessageUri.toString()); 1490fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen } 1491c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (errorCode != 0) { 1492c99dab56e20222b28cbc6238645feac938f1c333Ye Wen fillIn.putExtra("errorCode", errorCode); 1493c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1494c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mUnsentPartCount != null && isSinglePartOrLastPart) { 1495c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // Is multipart and last part 1496c99dab56e20222b28cbc6238645feac938f1c333Ye Wen fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true); 1497c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1498c99dab56e20222b28cbc6238645feac938f1c333Ye Wen mSentIntent.send(context, error, fillIn); 1499c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } catch (CanceledException ex) { 1500c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Failed to send result"); 1501c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1502c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1503c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1504c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1505c99dab56e20222b28cbc6238645feac938f1c333Ye Wen /** 1506c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * Handle the sent of a single part message or a part of a multipart message 1507c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * 1508c99dab56e20222b28cbc6238645feac938f1c333Ye Wen * @param context The Context 1509c99dab56e20222b28cbc6238645feac938f1c333Ye Wen */ 1510c99dab56e20222b28cbc6238645feac938f1c333Ye Wen public void onSent(Context context) { 1511c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // is single part or last part of multipart message 1512c99dab56e20222b28cbc6238645feac938f1c333Ye Wen boolean isSinglePartOrLastPart = true; 1513c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mUnsentPartCount != null) { 1514c99dab56e20222b28cbc6238645feac938f1c333Ye Wen isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0; 1515c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1516c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (isSinglePartOrLastPart) { 15174bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen int messageType = Sms.MESSAGE_TYPE_SENT; 1518c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mAnyPartFailed != null && mAnyPartFailed.get()) { 15194bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen messageType = Sms.MESSAGE_TYPE_FAILED; 1520c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 15214bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen persistOrUpdateMessage(context, messageType, 0/*errorCode*/); 1522c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1523c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mSentIntent != null) { 1524c99dab56e20222b28cbc6238645feac938f1c333Ye Wen try { 1525fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen // Extra information to send with the sent intent 1526fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen Intent fillIn = new Intent(); 1527fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen if (mMessageUri != null) { 1528fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen // Pass this to SMS apps so that they know where it is stored 1529fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen fillIn.putExtra("uri", mMessageUri.toString()); 1530fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen } 1531c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (mUnsentPartCount != null && isSinglePartOrLastPart) { 1532c99dab56e20222b28cbc6238645feac938f1c333Ye Wen // Is multipart and last part 1533fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true); 1534c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1535fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen mSentIntent.send(context, Activity.RESULT_OK, fillIn); 1536c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } catch (CanceledException ex) { 1537c99dab56e20222b28cbc6238645feac938f1c333Ye Wen Rlog.e(TAG, "Failed to send result"); 1538c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 15390217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun } 15400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 15420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1543ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected SmsTracker getSmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, 1544c99dab56e20222b28cbc6238645feac938f1c333Ye Wen PendingIntent deliveryIntent, String format, AtomicInteger unsentPartCount, 15456ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi AtomicBoolean anyPartFailed, Uri messageUri, SmsHeader smsHeader, 1546a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang boolean isExpectMore, String fullMessageText, boolean isText, boolean persistMessage) { 15471260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Get calling app package name via UID from Binder call 15481260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa PackageManager pm = mContext.getPackageManager(); 15491260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String[] packageNames = pm.getPackagesForUid(Binder.getCallingUid()); 15501260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 15511260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Get package info via packagemanager 15521260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa PackageInfo appInfo = null; 15531260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa if (packageNames != null && packageNames.length > 0) { 15541260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa try { 15551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // XXX this is lossy- apps can share a UID 15561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa appInfo = pm.getPackageInfo(packageNames[0], PackageManager.GET_SIGNATURES); 15571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } catch (PackageManager.NameNotFoundException e) { 15581260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // error will be logged in sendRawPdu 15591260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 15601260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 15611260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // Strip non-digits from destination phone number before checking for short codes 15621260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa // and before displaying the number to the user if confirmation is required. 15631260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String destAddr = PhoneNumberUtils.extractNetworkPortion((String) data.get("destAddr")); 1564c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return new SmsTracker(data, sentIntent, deliveryIntent, appInfo, destAddr, format, 15654bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen unsentPartCount, anyPartFailed, messageUri, smsHeader, isExpectMore, 1566a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang fullMessageText, getSubId(), isText, persistMessage); 1567c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1568c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1569c99dab56e20222b28cbc6238645feac938f1c333Ye Wen protected SmsTracker getSmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, 15704bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen PendingIntent deliveryIntent, String format, Uri messageUri, boolean isExpectMore, 1571a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang String fullMessageText, boolean isText, boolean persistMessage) { 1572c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return getSmsTracker(data, sentIntent, deliveryIntent, format, null/*unsentPartCount*/, 15734bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen null/*anyPartFailed*/, messageUri, null/*smsHeader*/, isExpectMore, 1574a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang fullMessageText, isText, persistMessage); 15751260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 15761260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1577ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr, 15781260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa String text, SmsMessageBase.SubmitPduBase pdu) { 15791260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa HashMap<String, Object> map = new HashMap<String, Object>(); 15801260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("destAddr", destAddr); 15811260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("scAddr", scAddr); 15821260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("text", text); 15831260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("smsc", pdu.encodedScAddress); 15841260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("pdu", pdu.encodedMessage); 15851260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa return map; 15861260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 15871260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1588ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr, 15891260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu) { 15901260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa HashMap<String, Object> map = new HashMap<String, Object>(); 15911260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("destAddr", destAddr); 15921260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("scAddr", scAddr); 1593ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa map.put("destPort", destPort); 15941260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("data", data); 15951260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("smsc", pdu.encodedScAddress); 15961260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa map.put("pdu", pdu.encodedMessage); 15971260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa return map; 15981260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa } 15991260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 16000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 16010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Dialog listener for SMS confirmation dialog. 16020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 16030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final class ConfirmDialogListener 16044658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, 16054658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby CompoundButton.OnCheckedChangeListener { 16060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final SmsTracker mTracker; 16084658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby private Button mPositiveButton; 16094658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby private Button mNegativeButton; 16104658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby private boolean mRememberChoice; // default is unchecked 161178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt private final TextView mRememberUndoInstruction; 16120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 161378df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt ConfirmDialogListener(SmsTracker tracker, TextView textView) { 16140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mTracker = tracker; 161578df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction = textView; 16160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16184658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby void setPositiveButton(Button button) { 16194658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mPositiveButton = button; 16204658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 16214658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 16224658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby void setNegativeButton(Button button) { 16234658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mNegativeButton = button; 16244658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 16254658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 16260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 16270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void onClick(DialogInterface dialog, int which) { 16284658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // Always set the SMS permission so that Settings will show a permission setting 16294658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby // for the app (it won't be shown until after the app tries to send to a short code). 16304658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby int newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER; 16314658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 16320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (which == DialogInterface.BUTTON_POSITIVE) { 1633ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "CONFIRM sending SMS"); 16342029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // XXX this is lossy- apps can have more than one signature 1635634a24f56f54b5d2911649288147c750b67c7ae4William Luh EventLog.writeEvent(EventLogTags.EXP_DET_SMS_SENT_BY_USER, 1636ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh mTracker.mAppInfo.applicationInfo == null ? 1637ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh -1 : mTracker.mAppInfo.applicationInfo.uid); 16380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_SEND_CONFIRMED_SMS, mTracker)); 16394658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (mRememberChoice) { 16404658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW; 16414658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 16420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else if (which == DialogInterface.BUTTON_NEGATIVE) { 1643ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "DENY sending SMS"); 16442029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra // XXX this is lossy- apps can have more than one signature 1645634a24f56f54b5d2911649288147c750b67c7ae4William Luh EventLog.writeEvent(EventLogTags.EXP_DET_SMS_DENIED_BY_USER, 1646ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh mTracker.mAppInfo.applicationInfo == null ? 1647ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh -1 : mTracker.mAppInfo.applicationInfo.uid); 16480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_STOP_SENDING, mTracker)); 16494658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (mRememberChoice) { 16504658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW; 16514658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 16520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16534658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby setPremiumSmsPermission(mTracker.mAppInfo.packageName, newSmsPermission); 16540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 16560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 16570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void onCancel(DialogInterface dialog) { 1658ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "dialog dismissed: don't send SMS"); 16590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville sendMessage(obtainMessage(EVENT_STOP_SENDING, mTracker)); 16600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16614658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby 16624658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby @Override 16634658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1664ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(TAG, "remember this choice: " + isChecked); 16654658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mRememberChoice = isChecked; 16664658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby if (isChecked) { 16674658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mPositiveButton.setText(R.string.sms_short_code_confirm_always_allow); 16684658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mNegativeButton.setText(R.string.sms_short_code_confirm_never_allow); 166978df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt if (mRememberUndoInstruction != null) { 167078df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction. 167178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt setText(R.string.sms_short_code_remember_undo_instruction); 167278df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction.setPadding(0,0,0,32); 167378df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt } 16744658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } else { 16754658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby mPositiveButton.setText(R.string.sms_short_code_confirm_allow); 16765d875796122cdd8a7004e8e3964b20b5c65a31a1Robert Greenwalt mNegativeButton.setText(R.string.sms_short_code_confirm_deny); 167778df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt if (mRememberUndoInstruction != null) { 167878df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction.setText(""); 167978df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt mRememberUndoInstruction.setPadding(0,0,0,0); 168078df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt } 16814658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 16824658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby } 16830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 16841260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1685ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa public boolean isIms() { 1686ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa if (mImsSMSDispatcher != null) { 1687ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return mImsSMSDispatcher.isIms(); 1688ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } else { 1689ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa Rlog.e(TAG, mImsSMSDispatcher + " is null"); 1690ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return false; 1691ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1692ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 16931260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa 1694ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa public String getImsSmsFormat() { 1695ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa if (mImsSMSDispatcher != null) { 1696ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return mImsSMSDispatcher.getImsSmsFormat(); 1697ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } else { 1698ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa Rlog.e(TAG, mImsSMSDispatcher + " is null"); 1699ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa return null; 1700ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1701ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa } 1702c99dab56e20222b28cbc6238645feac938f1c333Ye Wen 1703c99dab56e20222b28cbc6238645feac938f1c333Ye Wen private String getMultipartMessageText(ArrayList<String> parts) { 1704c99dab56e20222b28cbc6238645feac938f1c333Ye Wen final StringBuilder sb = new StringBuilder(); 1705c99dab56e20222b28cbc6238645feac938f1c333Ye Wen for (String part : parts) { 1706c99dab56e20222b28cbc6238645feac938f1c333Ye Wen if (part != null) { 1707c99dab56e20222b28cbc6238645feac938f1c333Ye Wen sb.append(part); 1708c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1709c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1710c99dab56e20222b28cbc6238645feac938f1c333Ye Wen return sb.toString(); 1711c99dab56e20222b28cbc6238645feac938f1c333Ye Wen } 1712b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen 17138215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang protected String getCarrierAppPackageName() { 1714062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId()); 17157f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal if (card == null) { 17167f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal return null; 17177f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal } 17187f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal 1719934a24a6aa2b7a981e872fa350648904ed80280aDiego Pontoriero List<String> carrierPackages = card.getCarrierPackageNamesForIntent( 17208215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang mContext.getPackageManager(), new Intent(CarrierMessagingService.SERVICE_INTERFACE)); 17217f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal return (carrierPackages != null && carrierPackages.size() == 1) ? 17227f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal carrierPackages.get(0) : null; 1723c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal } 1724c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal 1725b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville protected int getSubId() { 172614bdfdca7a5412edf5fbdd6573e0f608233a5ae8Amit Mahajan return SubscriptionController.getInstance().getSubIdUsingPhoneId(mPhone.getPhoneId()); 1727b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 1728f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal 1729f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal private void checkCallerIsPhoneOrCarrierApp() { 1730f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal int uid = Binder.getCallingUid(); 1731f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal int appId = UserHandle.getAppId(uid); 1732f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal if (appId == Process.PHONE_UID || uid == 0) { 1733f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal return; 1734f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal } 1735f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal try { 1736f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal PackageManager pm = mContext.getPackageManager(); 1737f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal ApplicationInfo ai = pm.getApplicationInfo(getCarrierAppPackageName(), 0); 1738f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal if (!UserHandle.isSameApp(ai.uid, Binder.getCallingUid())) { 1739f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal throw new SecurityException("Caller is not phone or carrier app!"); 1740f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal } 1741f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal } catch (PackageManager.NameNotFoundException re) { 1742f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal throw new SecurityException("Caller is not phone or carrier app!"); 1743f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal } 1744f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal } 17450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville} 1746