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;
1896f2245d927c81fcd348bace3bc417bd0f91fb33Abhijith Shastry
1996f2245d927c81fcd348bace3bc417bd0f91fb33Abhijith Shastryimport static android.Manifest.permission.SEND_SMS_NO_CONFIRMATION;
2096f2245d927c81fcd348bace3bc417bd0f91fb33Abhijith Shastryimport static android.telephony.SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE;
2196f2245d927c81fcd348bace3bc417bd0f91fb33Abhijith Shastryimport static android.telephony.SmsManager.RESULT_ERROR_GENERIC_FAILURE;
2296f2245d927c81fcd348bace3bc417bd0f91fb33Abhijith Shastryimport static android.telephony.SmsManager.RESULT_ERROR_LIMIT_EXCEEDED;
2396f2245d927c81fcd348bace3bc417bd0f91fb33Abhijith Shastryimport static android.telephony.SmsManager.RESULT_ERROR_NO_SERVICE;
2496f2245d927c81fcd348bace3bc417bd0f91fb33Abhijith Shastryimport static android.telephony.SmsManager.RESULT_ERROR_NULL_PDU;
2596f2245d927c81fcd348bace3bc417bd0f91fb33Abhijith Shastryimport static android.telephony.SmsManager.RESULT_ERROR_RADIO_OFF;
26d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqianimport static android.telephony.SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED;
27d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqianimport static android.telephony.SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED;
2896f2245d927c81fcd348bace3bc417bd0f91fb33Abhijith Shastry
29ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wangimport android.annotation.Nullable;
3032cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Makimport android.annotation.UserIdInt;
310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.Activity;
320825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.AlertDialog;
330825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.PendingIntent;
340825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.PendingIntent.CanceledException;
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.ContentResolver;
360217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.content.ContentValues;
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Context;
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.DialogInterface;
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Intent;
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.ApplicationInfo;
412029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condraimport android.content.pm.PackageInfo;
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.PackageManager;
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.res.Resources;
44ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwaltimport android.database.ContentObserver;
450217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.database.sqlite.SqliteWrapper;
460217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.net.Uri;
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult;
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Binder;
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler;
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message;
51f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawalimport android.os.Process;
528215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.os.RemoteException;
53f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawalimport android.os.UserHandle;
54ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwaltimport android.provider.Settings;
550217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.provider.Telephony;
560217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braunimport android.provider.Telephony.Sms;
578215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.service.carrier.CarrierMessagingService;
588215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.service.carrier.ICarrierMessagingCallback;
598215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.service.carrier.ICarrierMessagingService;
608215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wangimport android.telephony.CarrierMessagingServiceManager;
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.PhoneNumberUtils;
620d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.Rlog;
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.ServiceState;
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.TelephonyManager;
650825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.Html;
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.Spanned;
67b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.text.TextUtils;
682029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condraimport android.util.EventLog;
694658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.view.LayoutInflater;
704658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.view.View;
7178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwaltimport android.view.ViewGroup;
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.WindowManager;
734658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.Button;
744658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.CheckBox;
754658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.CompoundButton;
764658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hambyimport android.widget.TextView;
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.R;
79ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqianimport com.android.internal.annotations.VisibleForTesting;
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
81a9552aa6bf3ce12c75ad43165034d9a1233fb131Shishir Agrawalimport com.android.internal.telephony.uicc.UiccCard;
82c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport com.android.internal.telephony.uicc.UiccController;
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList;
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.HashMap;
868d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wangimport java.util.List;
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Random;
88c99dab56e20222b28cbc6238645feac938f1c333Ye Wenimport java.util.concurrent.atomic.AtomicBoolean;
890d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.util.concurrent.atomic.AtomicInteger;
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic abstract class SMSDispatcher extends Handler {
92cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    static final String TAG = "SMSDispatcher";    // accessed from inner class
93cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    static final boolean DBG = false;
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String SEND_NEXT_MSG_EXTRA = "SendNextMsg";
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
96ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt    private static final int PREMIUM_RULE_USE_SIM = 1;
97ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt    private static final int PREMIUM_RULE_USE_NETWORK = 2;
98ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt    private static final int PREMIUM_RULE_USE_BOTH = 3;
99ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt    private final AtomicInteger mPremiumSmsRule = new AtomicInteger(PREMIUM_RULE_USE_SIM);
100ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt    private final SettingsObserver mSettingsObserver;
101ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** SMS send complete. */
1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected static final int EVENT_SEND_SMS_COMPLETE = 2;
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Retry sending a previously failed SMS message */
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int EVENT_SEND_RETRY = 3;
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Confirmation required for sending a large number of messages. */
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int EVENT_SEND_LIMIT_REACHED_CONFIRMATION = 4;
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Send the user confirmed SMS */
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int EVENT_SEND_CONFIRMED_SMS = 5;  // accessed from inner class
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Don't send SMS (user did not confirm). */
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int EVENT_STOP_SENDING = 7;        // accessed from inner class
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Confirmation required for third-party apps sending to an SMS short code. */
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE = 8;
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Confirmation required for third-party apps sending to an SMS short code. */
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE = 9;
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1230d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /** Handle status report from {@code CdmaInboundSmsHandler}. */
1240d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected static final int EVENT_HANDLE_STATUS_REPORT = 10;
1250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1261260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    /** Radio is ON */
1271260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    protected static final int EVENT_RADIO_ON = 11;
1281260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
1291260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    /** IMS registration/SMS format changed */
1301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    protected static final int EVENT_IMS_STATE_CHANGED = 12;
1311260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
1321260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    /** Callback from RIL_REQUEST_IMS_REGISTRATION_STATE */
1331260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    protected static final int EVENT_IMS_STATE_DONE = 13;
1341260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
1351260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    // other
1361260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    protected static final int EVENT_NEW_ICC_SMS = 14;
1371260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    protected static final int EVENT_ICC_CHANGED = 15;
1381260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
1391a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu    protected Phone mPhone;
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected final Context mContext;
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected final ContentResolver mResolver;
14222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    protected final CommandsInterface mCi;
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected final TelephonyManager mTelephonyManager;
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Maximum number of times to retry sending a failed SMS. */
1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int MAX_SEND_RETRIES = 3;
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Delay before next send attempt on a failed SMS, in milliseconds. */
1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int SEND_RETRY_DELAY = 2000;
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** single part SMS */
1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int SINGLE_PART_SMS = 1;
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Message sending queue limit */
1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int MO_MSG_QUEUE_LIMIT = 5;
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Message reference for a CONCATENATED_8_BIT_REFERENCE or
1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * CONCATENATED_16_BIT_REFERENCE message set.  Should be
1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * incremented for each set of concatenated messages.
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Static field shared by all dispatcher objects.
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static int sConcatenatedRef = new Random().nextInt(256);
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Outgoing message counter. Shared by all dispatchers. */
1631260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    private SmsUsageMonitor mUsageMonitor;
1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
165ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa    private ImsSMSDispatcher mImsSMSDispatcher;
166ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa
1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Number of outgoing SmsTrackers waiting for user confirmation. */
1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int mPendingTrackerCount;
1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /* Flags indicating whether the current device allows sms service */
1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected boolean mSmsCapable = true;
1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected boolean mSmsSendDisabled;
1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected static int getNextConcatenatedRef() {
1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        sConcatenatedRef += 1;
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return sConcatenatedRef;
1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Create a new SMS dispatcher.
1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param phone the Phone to use
1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param usageMonitor the SmsUsageMonitor to use
1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1841a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu    protected SMSDispatcher(Phone phone, SmsUsageMonitor usageMonitor,
185ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            ImsSMSDispatcher imsSMSDispatcher) {
1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mPhone = phone;
187ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        mImsSMSDispatcher = imsSMSDispatcher;
1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mContext = phone.getContext();
1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mResolver = mContext.getContentResolver();
19022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mCi = phone.mCi;
1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mUsageMonitor = usageMonitor;
1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
193ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt        mSettingsObserver = new SettingsObserver(this, mPremiumSmsRule, mContext);
194ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt        mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
195ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt                Settings.Global.SMS_SHORT_CODE_RULE), false, mSettingsObserver);
1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mSmsCapable = mContext.getResources().getBoolean(
1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                com.android.internal.R.bool.config_sms_capable);
199e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu        mSmsSendDisabled = !mTelephonyManager.getSmsSendCapableForPhone(
200e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu                mPhone.getPhoneId(), mSmsCapable);
201ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(TAG, "SMSDispatcher: ctor mSmsCapable=" + mSmsCapable + " format=" + getFormat()
2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                + " mSmsSendDisabled=" + mSmsSendDisabled);
2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
205ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt    /**
206ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt     * Observe the secure setting for updated premium sms determination rules
207ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt     */
208ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt    private static class SettingsObserver extends ContentObserver {
209ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt        private final AtomicInteger mPremiumSmsRule;
210ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt        private final Context mContext;
211ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt        SettingsObserver(Handler handler, AtomicInteger premiumSmsRule, Context context) {
212ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt            super(handler);
213ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt            mPremiumSmsRule = premiumSmsRule;
214ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt            mContext = context;
215ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt            onChange(false); // load initial value;
216ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt        }
217ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt
218ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt        @Override
219ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt        public void onChange(boolean selfChange) {
220ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt            mPremiumSmsRule.set(Settings.Global.getInt(mContext.getContentResolver(),
221ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt                    Settings.Global.SMS_SHORT_CODE_RULE, PREMIUM_RULE_USE_SIM));
222ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt        }
223ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt    }
224ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt
2251a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu    protected void updatePhoneObject(Phone phone) {
2261260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        mPhone = phone;
2271260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        mUsageMonitor = phone.mSmsUsageMonitor;
2281260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        Rlog.d(TAG, "Active phone changed to " + mPhone.getPhoneName() );
2291260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
2301260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Unregister for incoming SMS events. */
2320d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    public void dispose() {
2330d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mContext.getContentResolver().unregisterContentObserver(mSettingsObserver);
2340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * The format of the message PDU in the associated broadcast intent.
2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * This will be either "3gpp" for GSM/UMTS/LTE messages in 3GPP format
2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * or "3gpp2" for CDMA/LTE messages in 3GPP2 format.
2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Note: All applications which handle incoming SMS messages by processing the
2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * SMS_RECEIVED_ACTION broadcast intent MUST pass the "format" extra from the intent
2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * into the new methods in {@link android.telephony.SmsMessage} which take an
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * extra format parameter. This is required in order to correctly decode the PDU on
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * devices which require support for both 3GPP and 3GPP2 formats at the same time,
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * such as CDMA/LTE devices and GSM/CDMA world phones.
2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return the format of the message PDU
2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected abstract String getFormat();
2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
2530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Pass the Message object to subclass to handle. Currently used to pass CDMA status reports
2540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * from {@link com.android.internal.telephony.cdma.CdmaInboundSmsHandler}.
2550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param o the SmsMessage containing the status report
2560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
2570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected void handleStatusReport(Object o) {
2580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        Rlog.d(TAG, "handleStatusReport() called with no subclass.");
2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /* TODO: Need to figure out how to keep track of status report routing in a
2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *       persistent manner. If the phone process restarts (reboot or crash),
2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *       we will lose this list and any status reports that come in after
2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *       will be dropped.
2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Sent messages awaiting a delivery status report. */
2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected final ArrayList<SmsTracker> deliveryPendingList = new ArrayList<SmsTracker>();
2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Handles events coming from the phone stack. Overridden from handler.
2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param msg the message to handle
2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void handleMessage(Message msg) {
2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (msg.what) {
2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case EVENT_SEND_SMS_COMPLETE:
2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // An outbound SMS has been successfully transferred, or failed.
2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            handleSendComplete((AsyncResult) msg.obj);
2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case EVENT_SEND_RETRY:
2831260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            Rlog.d(TAG, "SMS retry..");
2841260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            sendRetrySms((SmsTracker) msg.obj);
2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case EVENT_SEND_LIMIT_REACHED_CONFIRMATION:
2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            handleReachSentLimit((SmsTracker)(msg.obj));
2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE:
2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            handleConfirmShortCode(false, (SmsTracker)(msg.obj));
2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE:
2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            handleConfirmShortCode(true, (SmsTracker)(msg.obj));
2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case EVENT_SEND_CONFIRMED_SMS:
3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {
3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            SmsTracker tracker = (SmsTracker) msg.obj;
3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (tracker.isMultipart()) {
3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sendMultipartSms(tracker);
3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
3056c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying                if (mPendingTrackerCount > 1) {
3066c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying                    tracker.mExpectMore = true;
3076c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying                } else {
3086c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying                    tracker.mExpectMore = false;
3096c376fea69306e22a2f11894d05cd0abfdaefed3Xia Ying                }
3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sendSms(tracker);
3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mPendingTrackerCount--;
3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case EVENT_STOP_SENDING:
3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        {
3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            SmsTracker tracker = (SmsTracker) msg.obj;
319d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian            if (msg.arg1 == ConfirmDialogListener.SHORT_CODE_MSG) {
320d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                if (msg.arg2 == ConfirmDialogListener.NEVER_ALLOW) {
321d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                    tracker.onFailed(mContext,
322d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                            RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED, 0/*errorCode*/);
323d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                    Rlog.d(TAG, "SMSDispatcher: EVENT_STOP_SENDING - "
324d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                            + "sending SHORT_CODE_NEVER_ALLOWED error code.");
325d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                } else {
326d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                    tracker.onFailed(mContext,
327d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                            RESULT_ERROR_SHORT_CODE_NOT_ALLOWED, 0/*errorCode*/);
328d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                    Rlog.d(TAG, "SMSDispatcher: EVENT_STOP_SENDING - "
329d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                            + "sending SHORT_CODE_NOT_ALLOWED error code.");
330d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                }
331d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian            } else if (msg.arg1 == ConfirmDialogListener.RATE_LIMIT) {
332d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                tracker.onFailed(mContext, RESULT_ERROR_LIMIT_EXCEEDED, 0/*errorCode*/);
333d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                Rlog.d(TAG, "SMSDispatcher: EVENT_STOP_SENDING - "
334d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                        + "sending LIMIT_EXCEEDED error code.");
335d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian            } else {
336d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                Rlog.e(TAG, "SMSDispatcher: EVENT_STOP_SENDING - unexpected cases.");
337d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian            }
3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mPendingTrackerCount--;
3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        case EVENT_HANDLE_STATUS_REPORT:
3430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            handleStatusReport(msg.obj);
3440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            break;
3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        default:
3470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            Rlog.e(TAG, "handleMessage() ignoring message of unexpected type " + msg.what);
3480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
349b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby    }
350b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby
351b8a13d300b245e0080aa01275e232f54d5d0e09cJake Hamby    /**
3528215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     * Use the carrier messaging service to send a data or text SMS.
3538215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     */
3548215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    protected abstract class SmsSender extends CarrierMessagingServiceManager {
3558215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        protected final SmsTracker mTracker;
3568215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        // Initialized in sendSmsByCarrierApp
3578215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        protected volatile SmsSenderCallback mSenderCallback;
3588215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
3598215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        protected SmsSender(SmsTracker tracker) {
3608215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            mTracker = tracker;
3618215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
3628215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
3638215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public void sendSmsByCarrierApp(String carrierPackageName,
3648215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                                        SmsSenderCallback senderCallback) {
3658215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            mSenderCallback = senderCallback;
3668215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            if (!bindToCarrierMessagingService(mContext, carrierPackageName)) {
3678215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                Rlog.e(TAG, "bindService() for carrier messaging service failed");
3688215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                mSenderCallback.onSendSmsComplete(
3698215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                        CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
3708215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                        0 /* messageRef */);
3718215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            } else {
3728215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                Rlog.d(TAG, "bindService() for carrier messaging service succeeded");
3738215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            }
3748215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
3758215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    }
3768215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
377ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang    private static int getSendSmsFlag(@Nullable PendingIntent deliveryIntent) {
378ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang        if (deliveryIntent == null) {
379ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang            return 0;
380ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang        }
381ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang        return CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS;
382ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang    }
383ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang
3848215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    /**
3858215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     * Use the carrier messaging service to send a text SMS.
3868215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     */
3878215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    protected final class TextSmsSender extends SmsSender {
3888215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public TextSmsSender(SmsTracker tracker) {
3898215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            super(tracker);
3908215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
3918215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
3928215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
3938215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        protected void onServiceReady(ICarrierMessagingService carrierMessagingService) {
3945d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan            HashMap<String, Object> map = mTracker.getData();
3958215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            String text = (String) map.get("text");
3968215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
3978215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            if (text != null) {
3988215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                try {
3998215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                    carrierMessagingService.sendTextSms(text, getSubId(),
400ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang                            mTracker.mDestAddress, getSendSmsFlag(mTracker.mDeliveryIntent),
401ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang                            mSenderCallback);
4028215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                } catch (RemoteException e) {
4038215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                    Rlog.e(TAG, "Exception sending the SMS: " + e);
4048215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                    mSenderCallback.onSendSmsComplete(
4058215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                            CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
4068215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                            0 /* messageRef */);
4078215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                }
4088215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            } else {
4098215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                mSenderCallback.onSendSmsComplete(
4108215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                        CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
4118215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                        0 /* messageRef */);
4128215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            }
4138215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
4148215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    }
4158215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
4168215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    /**
4178215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     * Use the carrier messaging service to send a data SMS.
4188215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     */
4198215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    protected final class DataSmsSender extends SmsSender {
4208215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public DataSmsSender(SmsTracker tracker) {
4218215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            super(tracker);
4228215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
4238215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
4248215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
4258215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        protected void onServiceReady(ICarrierMessagingService carrierMessagingService) {
4265d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan            HashMap<String, Object> map = mTracker.getData();
4278215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            byte[] data = (byte[]) map.get("data");
4288215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            int destPort = (int) map.get("destPort");
4298215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
4308215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            if (data != null) {
4318215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                try {
4328215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                    carrierMessagingService.sendDataSms(data, getSubId(),
433ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang                            mTracker.mDestAddress, destPort,
434ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang                            getSendSmsFlag(mTracker.mDeliveryIntent), mSenderCallback);
4358215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                } catch (RemoteException e) {
4368215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                    Rlog.e(TAG, "Exception sending the SMS: " + e);
4378215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                    mSenderCallback.onSendSmsComplete(
4388215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                            CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
4398215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                            0 /* messageRef */);
4408215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                }
4418215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            } else {
4428215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                mSenderCallback.onSendSmsComplete(
4438215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                        CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
4448215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                        0 /* messageRef */);
4458215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            }
4468215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
4478215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    }
4488215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
4498215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    /**
4508215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     * Callback for TextSmsSender and DataSmsSender from the carrier messaging service.
4518215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     * Once the result is ready, the carrier messaging service connection is disposed.
4528215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     */
4538215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    protected final class SmsSenderCallback extends ICarrierMessagingCallback.Stub {
4548215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        private final SmsSender mSmsSender;
4558215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
4568215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public SmsSenderCallback(SmsSender smsSender) {
4578215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            mSmsSender = smsSender;
4588215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
4598215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
4608215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        /**
4618215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang         * This method should be called only once.
4628215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang         */
4638215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
4648215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public void onSendSmsComplete(int result, int messageRef) {
465f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            checkCallerIsPhoneOrCarrierApp();
466f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            final long identity = Binder.clearCallingIdentity();
467f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            try {
468f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal                mSmsSender.disposeConnection(mContext);
469f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal                processSendSmsResponse(mSmsSender.mTracker, result, messageRef);
470f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            } finally {
471f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal                Binder.restoreCallingIdentity(identity);
472f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            }
4738215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
4748215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
4758215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
4768215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public void onSendMultipartSmsComplete(int result, int[] messageRefs) {
4778215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.e(TAG, "Unexpected onSendMultipartSmsComplete call with result: " + result);
4788215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
4798215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
4808215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
4813fcaeac48c45f7fbefd2aeee8fe3094f40f9bf84Ji Yang        public void onFilterComplete(int result) {
4823fcaeac48c45f7fbefd2aeee8fe3094f40f9bf84Ji Yang            Rlog.e(TAG, "Unexpected onFilterComplete call with result: " + result);
4838215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
4848215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
4858215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
4868215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public void onSendMmsComplete(int result, byte[] sendConfPdu) {
4878215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.e(TAG, "Unexpected onSendMmsComplete call with result: " + result);
4888215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
4898215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
4908215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
4918215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public void onDownloadMmsComplete(int result) {
4928215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.e(TAG, "Unexpected onDownloadMmsComplete call with result: " + result);
4938215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
4948215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    }
4958215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
4968215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    private void processSendSmsResponse(SmsTracker tracker, int result, int messageRef) {
4978215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        if (tracker == null) {
4988215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.e(TAG, "processSendSmsResponse: null tracker");
4998215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            return;
5008215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
5018215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
5028215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        SmsResponse smsResponse = new SmsResponse(
5038215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                messageRef, null /* ackPdu */, -1 /* unknown error code */);
5048215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
5058215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        switch (result) {
5068215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        case CarrierMessagingService.SEND_STATUS_OK:
5078215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.d(TAG, "Sending SMS by IP succeeded.");
5088215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE,
5098215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                                      new AsyncResult(tracker,
5108215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                                                      smsResponse,
5118215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                                                      null /* exception*/ )));
5128215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            break;
5138215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        case CarrierMessagingService.SEND_STATUS_ERROR:
5148215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.d(TAG, "Sending SMS by IP failed.");
5158215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE,
5168215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                    new AsyncResult(tracker, smsResponse,
5178215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                            new CommandException(CommandException.Error.GENERIC_FAILURE))));
5188215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            break;
5198215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        case CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK:
5208215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.d(TAG, "Sending SMS by IP failed. Retry on carrier network.");
5218215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            sendSubmitPdu(tracker);
5228215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            break;
5238215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        default:
5248215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.d(TAG, "Unknown result " + result + " Retry on carrier network.");
5258215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            sendSubmitPdu(tracker);
5268215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
5278215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    }
5288215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
5298215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    /**
5308215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     * Use the carrier messaging service to send a multipart text SMS.
5318215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     */
5328215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    private final class MultipartSmsSender extends CarrierMessagingServiceManager {
5338215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        private final List<String> mParts;
5348215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public final SmsTracker[] mTrackers;
5358215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        // Initialized in sendSmsByCarrierApp
5368215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        private volatile MultipartSmsSenderCallback mSenderCallback;
5378215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
5388215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        MultipartSmsSender(ArrayList<String> parts, SmsTracker[] trackers) {
5398215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            mParts = parts;
5408215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            mTrackers = trackers;
5418215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
5428215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
5438215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        void sendSmsByCarrierApp(String carrierPackageName,
5448215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                                 MultipartSmsSenderCallback senderCallback) {
5458215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            mSenderCallback = senderCallback;
5468215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            if (!bindToCarrierMessagingService(mContext, carrierPackageName)) {
5478215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                Rlog.e(TAG, "bindService() for carrier messaging service failed");
5488215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                mSenderCallback.onSendMultipartSmsComplete(
5498215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                        CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
5508215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                        null /* smsResponse */);
5518215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            } else {
5528215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                Rlog.d(TAG, "bindService() for carrier messaging service succeeded");
5538215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            }
5548215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
5558215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
5568215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
5578215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        protected void onServiceReady(ICarrierMessagingService carrierMessagingService) {
5588215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            try {
5598215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                carrierMessagingService.sendMultipartTextSms(
560ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang                        mParts, getSubId(), mTrackers[0].mDestAddress,
561ade6a7a40779f907ba34142ad2286d532fcdebffCheuksan Wang                        getSendSmsFlag(mTrackers[0].mDeliveryIntent), mSenderCallback);
5628215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            } catch (RemoteException e) {
5638215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                Rlog.e(TAG, "Exception sending the SMS: " + e);
5648215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                mSenderCallback.onSendMultipartSmsComplete(
5658215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                        CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
5668215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                        null /* smsResponse */);
5678215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            }
5688215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
5698215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    }
5708215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
5718215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    /**
5728215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     * Callback for MultipartSmsSender from the carrier messaging service.
5738215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     * Once the result is ready, the carrier messaging service connection is disposed.
5748215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     */
5758215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    private final class MultipartSmsSenderCallback extends ICarrierMessagingCallback.Stub {
5768215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        private final MultipartSmsSender mSmsSender;
5778215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
5788215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        MultipartSmsSenderCallback(MultipartSmsSender smsSender) {
5798215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            mSmsSender = smsSender;
5808215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
5818215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
5828215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
5838215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public void onSendSmsComplete(int result, int messageRef) {
5848215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.e(TAG, "Unexpected onSendSmsComplete call with result: " + result);
5858215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
5868215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
5878215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        /**
5888215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang         * This method should be called only once.
5898215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang         */
5908215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
5918215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public void onSendMultipartSmsComplete(int result, int[] messageRefs) {
5928215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            mSmsSender.disposeConnection(mContext);
5938215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
5948215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            if (mSmsSender.mTrackers == null) {
5958215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                Rlog.e(TAG, "Unexpected onSendMultipartSmsComplete call with null trackers.");
5968215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                return;
5978215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            }
5988215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
599f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            checkCallerIsPhoneOrCarrierApp();
600f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            final long identity = Binder.clearCallingIdentity();
601f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            try {
602f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal                for (int i = 0; i < mSmsSender.mTrackers.length; i++) {
603f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal                    int messageRef = 0;
604f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal                    if (messageRefs != null && messageRefs.length > i) {
605f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal                        messageRef = messageRefs[i];
606f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal                    }
607f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal                    processSendSmsResponse(mSmsSender.mTrackers[i], result, messageRef);
6088215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                }
609f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            } finally {
610f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal                Binder.restoreCallingIdentity(identity);
6118215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            }
6128215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
6138215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
6148215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
6153fcaeac48c45f7fbefd2aeee8fe3094f40f9bf84Ji Yang        public void onFilterComplete(int result) {
6163fcaeac48c45f7fbefd2aeee8fe3094f40f9bf84Ji Yang            Rlog.e(TAG, "Unexpected onFilterComplete call with result: " + result);
6178215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
6188215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
6198215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
6208215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public void onSendMmsComplete(int result, byte[] sendConfPdu) {
6218215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.e(TAG, "Unexpected onSendMmsComplete call with result: " + result);
6228215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
6238215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
6248215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        @Override
6258215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        public void onDownloadMmsComplete(int result) {
6268215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.e(TAG, "Unexpected onDownloadMmsComplete call with result: " + result);
6278215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
6288215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    }
6298215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
6308215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    /**
6318215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     * Send an SMS PDU. Usually just calls {@link sendRawPdu}.
6328215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     */
6338215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    protected abstract void sendSubmitPdu(SmsTracker tracker);
6348215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
6358215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    /**
6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Called when SMS send completes. Broadcasts a sentIntent on success.
6370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * On failure, either sets up retries or broadcasts a sentIntent with
6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * the failure in the result code.
6390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param ar AsyncResult passed into the message handler.  ar.result should
6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *           an SmsResponse instance if send was successful.  ar.userObj
6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *           should be an SmsTracker instance.
6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void handleSendComplete(AsyncResult ar) {
6450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SmsTracker tracker = (SmsTracker) ar.userObj;
6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        PendingIntent sentIntent = tracker.mSentIntent;
6470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
648454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks        if (ar.result != null) {
6495a176f73dbb2bff2ca8b8f86af86a17be6863b87Wink Saville            tracker.mMessageRef = ((SmsResponse)ar.result).mMessageRef;
650454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks        } else {
651454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks            Rlog.d(TAG, "SmsResponse was null");
652454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks        }
653454c5783e7695feec276325920550b2d4dcc3e16Rika Brooks
6540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (ar.exception == null) {
655cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville            if (DBG) Rlog.d(TAG, "SMS send complete. Broadcasting intent: " + sentIntent);
6560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (tracker.mDeliveryIntent != null) {
6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Expecting a status report.  Add it to the list.
6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                deliveryPendingList.add(tracker);
6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
661c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            tracker.onSent(mContext);
6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
663cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville            if (DBG) Rlog.d(TAG, "SMS send failed");
6640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int ss = mPhone.getServiceState().getState();
6660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6671260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if ( tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) {
6681260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                // This is retry after failure over IMS but voice is not available.
6691260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                // Set retry to max allowed, so no retry is sent and
6701260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                //   cause RESULT_ERROR_GENERIC_FAILURE to be returned to app.
6711260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                tracker.mRetryCount = MAX_SEND_RETRIES;
6721260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
6731260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                Rlog.d(TAG, "handleSendComplete: Skipping retry: "
6741260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                +" isIms()="+isIms()
6751260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                +" mRetryCount="+tracker.mRetryCount
6761260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                +" mImsRetry="+tracker.mImsRetry
6771260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                +" mMessageRef="+tracker.mMessageRef
6781260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                +" SS= "+mPhone.getServiceState().getState());
6791260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
6801260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
6811260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            // if sms over IMS is not supported on data and voice is not available...
6821260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
683c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                tracker.onFailed(mContext, getNotInServiceError(ss), 0/*errorCode*/);
6840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if ((((CommandException)(ar.exception)).getCommandError()
6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    == CommandException.Error.SMS_FAIL_RETRY) &&
6860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                   tracker.mRetryCount < MAX_SEND_RETRIES) {
6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Retry after a delay if needed.
6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // TODO: According to TS 23.040, 9.2.3.6, we should resend
6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //       with the same TP-MR as the failed message, and
6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //       TP-RD set to 1.  However, we don't have a means of
6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //       knowing the MR for the failed message (EF_SMSstatus
6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //       may or may not have the MR corresponding to this
6930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //       message, depending on the failure).  Also, in some
6940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                //       implementations this retry is handled by the baseband.
6950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                tracker.mRetryCount++;
6960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker);
6970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sendMessageDelayed(retryMsg, SEND_RETRY_DELAY);
698c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            } else {
699c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                int errorCode = 0;
700c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                if (ar.result != null) {
701c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    errorCode = ((SmsResponse)ar.result).mErrorCode;
702c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                }
7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int error = RESULT_ERROR_GENERIC_FAILURE;
7040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (((CommandException)(ar.exception)).getCommandError()
7050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        == CommandException.Error.FDN_CHECK_FAILURE) {
7060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    error = RESULT_ERROR_FDN_CHECK_FAILURE;
7070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
708c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                tracker.onFailed(mContext, error, errorCode);
7090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
7100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
7140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Handles outbound message when the phone is not in service.
7150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
7160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param ss     Current service state.  Valid values are:
7170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *                  OUT_OF_SERVICE
7180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *                  EMERGENCY_ONLY
7190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *                  POWER_OFF
7200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param sentIntent the PendingIntent to send the error to
7210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
7220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected static void handleNotInService(int ss, PendingIntent sentIntent) {
7230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (sentIntent != null) {
7240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
7250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ss == ServiceState.STATE_POWER_OFF) {
7260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    sentIntent.send(RESULT_ERROR_RADIO_OFF);
7270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
7280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    sentIntent.send(RESULT_ERROR_NO_SERVICE);
7290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
7300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (CanceledException ex) {}
7310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
735c99dab56e20222b28cbc6238645feac938f1c333Ye Wen     * @param ss service state
736c99dab56e20222b28cbc6238645feac938f1c333Ye Wen     * @return The result error based on input service state for not in service error
737c99dab56e20222b28cbc6238645feac938f1c333Ye Wen     */
738c99dab56e20222b28cbc6238645feac938f1c333Ye Wen    protected static int getNotInServiceError(int ss) {
739c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        if (ss == ServiceState.STATE_POWER_OFF) {
740c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            return RESULT_ERROR_RADIO_OFF;
741c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        }
742c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        return RESULT_ERROR_NO_SERVICE;
743c99dab56e20222b28cbc6238645feac938f1c333Ye Wen    }
744c99dab56e20222b28cbc6238645feac938f1c333Ye Wen
745c99dab56e20222b28cbc6238645feac938f1c333Ye Wen    /**
7460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Send a data based SMS to a specific application port.
7470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
7480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param destAddr the address to send the message to
7490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param scAddr is the service center address or null to use
7500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  the current default SMSC
7510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param destPort the port to deliver the message to
7520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param data the body of the message to send
7530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param sentIntent if not NULL this <code>PendingIntent</code> is
7540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  broadcast when the message is successfully sent, or failed.
7550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  The result code will be <code>Activity.RESULT_OK<code> for success,
7560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  or one of these errors:<br>
7570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
7580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
7590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_NULL_PDU</code><br>
7600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_NO_SERVICE</code><br>.
7610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
7620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  the extra "errorCode" containing a radio technology specific value,
7630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  generally only useful for troubleshooting.<br>
7640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  The per-application based SMS control checks sentIntent. If sentIntent
7650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  is NULL the caller will be checked against all unknown applications,
7660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  which cause smaller number of SMS to be sent in checking period.
7670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
7680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  broadcast when the message is delivered to the recipient.  The
7690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  raw pdu of the status report is in the extended data ("pdu").
7700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
7710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected abstract void sendData(String destAddr, String scAddr, int destPort,
7720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent);
7730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
7750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Send a text based SMS.
776b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen     *  @param destAddr the address to send the message to
7770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param scAddr is the service center address or null to use
7780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  the current default SMSC
7790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param text the body of the message to send
7800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param sentIntent if not NULL this <code>PendingIntent</code> is
7810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  broadcast when the message is successfully sent, or failed.
7820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  The result code will be <code>Activity.RESULT_OK<code> for success,
7830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  or one of these errors:<br>
7840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
7850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
7860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_NULL_PDU</code><br>
7870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_NO_SERVICE</code><br>.
7880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
7890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  the extra "errorCode" containing a radio technology specific value,
7900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  generally only useful for troubleshooting.<br>
7910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  The per-application based SMS control checks sentIntent. If sentIntent
7920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  is NULL the caller will be checked against all unknown applications,
7930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  which cause smaller number of SMS to be sent in checking period.
7940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
7950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  broadcast when the message is delivered to the recipient.  The
796b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen     * @param messageUri optional URI of the message if it is already stored in the system
797b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen     * @param callingPkg the calling package name
798a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang     * @param persistMessage whether to save the sent message into SMS DB for a
799a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang     *   non-default SMS app.
8000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
801b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    protected abstract void sendText(String destAddr, String scAddr, String text,
802b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen            PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri,
803a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            String callingPkg, boolean persistMessage);
8040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
80663418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     * Inject an SMS PDU into the android platform.
80763418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     *
80863418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     * @param pdu is the byte array of pdu to be injected into android telephony layer
80963418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     * @param format is the format of SMS pdu (3gpp or 3gpp2)
81063418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     * @param receivedIntent if not NULL this <code>PendingIntent</code> is
81163418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     *  broadcast when the message is successfully received by the
81263418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     *  android telephony layer. This intent is broadcasted at
81363418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     *  the same time an SMS received from radio is responded back.
81463418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni     */
81563418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    protected abstract void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent);
81663418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni
81763418bbd2a9d7cc88ae24cc5ae776c01d688fc3aAnil Muthineni    /**
8183ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan     * Calculate the number of septets needed to encode the message. This function should only be
8193ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan     * called for individual segments of multipart message.
8200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
8210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param messageBody the message to encode
8220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param use7bitOnly ignore (but still count) illegal characters if true
8230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return TextEncodingDetails
8240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
8250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected abstract TextEncodingDetails calculateLength(CharSequence messageBody,
8260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            boolean use7bitOnly);
8270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
8290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Send a multi-part text based SMS.
830b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen     *  @param destAddr the address to send the message to
8310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param scAddr is the service center address or null to use
8320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   the current default SMSC
8330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param parts an <code>ArrayList</code> of strings that, in order,
8340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   comprise the original message
8350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param sentIntents if not null, an <code>ArrayList</code> of
8360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   <code>PendingIntent</code>s (one for each message part) that is
8370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   broadcast when the corresponding message part has been sent.
8380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   The result code will be <code>Activity.RESULT_OK<code> for success,
8390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   or one of these errors:
8400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
8410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   <code>RESULT_ERROR_RADIO_OFF</code>
8420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   <code>RESULT_ERROR_NULL_PDU</code>
8430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   <code>RESULT_ERROR_NO_SERVICE</code>.
8440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  The per-application based SMS control checks sentIntent. If sentIntent
8450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  is NULL the caller will be checked against all unknown applications,
8460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  which cause smaller number of SMS to be sent in checking period.
8470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param deliveryIntents if not null, an <code>ArrayList</code> of
8480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   <code>PendingIntent</code>s (one for each message part) that is
8490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   broadcast when the corresponding message part has been delivered
8500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *   to the recipient.  The raw pdu of the status report is in the
851b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen     * @param messageUri optional URI of the message if it is already stored in the system
852b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen     * @param callingPkg the calling package name
853a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang     * @param persistMessage whether to save the sent message into SMS DB for a
854a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang     *   non-default SMS app.
8550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
8560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void sendMultipartText(String destAddr, String scAddr,
8570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
858a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg,
859a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            boolean persistMessage) {
8604bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen        final String fullMessageText = getMultipartMessageText(parts);
8610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int refNumber = getNextConcatenatedRef() & 0x00FF;
8620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int msgCount = parts.size();
8630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int encoding = SmsConstants.ENCODING_UNKNOWN;
8640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount];
8660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0; i < msgCount; i++) {
8670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            TextEncodingDetails details = calculateLength(parts.get(i), false);
8680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (encoding != details.codeUnitSize
8690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    && (encoding == SmsConstants.ENCODING_UNKNOWN
8700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            || encoding == SmsConstants.ENCODING_7BIT)) {
8710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                encoding = details.codeUnitSize;
8720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
8730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            encodingForParts[i] = details;
8740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
8750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8768215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        SmsTracker[] trackers = new SmsTracker[msgCount];
8778215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
878c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        // States to track at the message level (for all parts)
879c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        final AtomicInteger unsentPartCount = new AtomicInteger(msgCount);
880c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        final AtomicBoolean anyPartFailed = new AtomicBoolean(false);
881c99dab56e20222b28cbc6238645feac938f1c333Ye Wen
8820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0; i < msgCount; i++) {
8830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
8840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            concatRef.refNumber = refNumber;
8850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            concatRef.seqNumber = i + 1;  // 1-based sequence
8860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            concatRef.msgCount = msgCount;
8870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // TODO: We currently set this to true since our messaging app will never
8880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // send more than 255 parts (it converts the message to MMS well before that).
8890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // However, we should support 3rd party messaging apps that might need 16-bit
8900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // references
8910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Note:  It's not sufficient to just flip this bit to true; it will have
8920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // ripple effects (several calculations assume 8-bit ref).
8930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            concatRef.isEightBits = true;
8940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            SmsHeader smsHeader = new SmsHeader();
8950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            smsHeader.concatRef = concatRef;
8960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Set the national language tables for 3GPP 7-bit encoding, if enabled.
8980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (encoding == SmsConstants.ENCODING_7BIT) {
8990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                smsHeader.languageTable = encodingForParts[i].languageTable;
9000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable;
9010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
9020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            PendingIntent sentIntent = null;
9040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (sentIntents != null && sentIntents.size() > i) {
9050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sentIntent = sentIntents.get(i);
9060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
9070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            PendingIntent deliveryIntent = null;
9090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (deliveryIntents != null && deliveryIntents.size() > i) {
9100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                deliveryIntent = deliveryIntents.get(i);
9110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
9120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9138215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            trackers[i] =
9148215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                getNewSubmitPduTracker(destAddr, scAddr, parts.get(i), smsHeader, encoding,
9158215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                        sentIntent, deliveryIntent, (i == (msgCount - 1)),
9168215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                        unsentPartCount, anyPartFailed, messageUri, fullMessageText);
917a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            trackers[i].mPersistMessage = persistMessage;
9188215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
9198215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
9208215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        if (parts == null || trackers == null || trackers.length == 0
9218215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                || trackers[0] == null) {
9228215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.e(TAG, "Cannot send multipart text. parts=" + parts + " trackers=" + trackers);
9238215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            return;
9248215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        }
9258215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang
9268215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        String carrierPackage = getCarrierAppPackageName();
9278215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        if (carrierPackage != null) {
9288215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.d(TAG, "Found carrier package.");
9298215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            MultipartSmsSender smsSender = new MultipartSmsSender(parts, trackers);
9308215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            smsSender.sendSmsByCarrierApp(carrierPackage, new MultipartSmsSenderCallback(smsSender));
9318215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang        } else {
9328215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            Rlog.v(TAG, "No carrier package.");
9338215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            for (SmsTracker tracker : trackers) {
9348215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                if (tracker != null) {
9358215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                    sendSubmitPdu(tracker);
9368215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                } else {
9378215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                    Rlog.e(TAG, "Null tracker.");
9388215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang                }
9398215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            }
9400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
9420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
9448215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     * Create a new SubmitPdu and return the SMS tracker.
9450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
9468215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    protected abstract SmsTracker getNewSubmitPduTracker(String destinationAddress, String scAddress,
9470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String message, SmsHeader smsHeader, int encoding,
948c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart,
9494bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
9504bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            String fullMessageText);
9510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
9538215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang     * Send an SMS
9541260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * @param tracker will contain:
9551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * -smsc the SMSC to send the message through, or NULL for the
9560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  default SMSC
9571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * -pdu the raw PDU to send
9581260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * -sentIntent if not NULL this <code>Intent</code> is
9590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  broadcast when the message is successfully sent, or failed.
9600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  The result code will be <code>Activity.RESULT_OK<code> for success,
9610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  or one of these errors:
9620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
9630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_RADIO_OFF</code>
9640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_NULL_PDU</code>
9650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  <code>RESULT_ERROR_NO_SERVICE</code>.
9660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  The per-application based SMS control checks sentIntent. If sentIntent
9670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  is NULL the caller will be checked against all unknown applications,
9680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  which cause smaller number of SMS to be sent in checking period.
9691260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * -deliveryIntent if not NULL this <code>Intent</code> is
9700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  broadcast when the message is delivered to the recipient.  The
9710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *  raw pdu of the status report is in the extended data ("pdu").
9721260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * -param destAddr the destination phone number (for short code confirmation)
9730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
974ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian    @VisibleForTesting
975ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian    public void sendRawPdu(SmsTracker tracker) {
9765d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan        HashMap map = tracker.getData();
9771260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        byte pdu[] = (byte[]) map.get("pdu");
9781260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
9790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mSmsSendDisabled) {
980c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            Rlog.e(TAG, "Device does not support sending sms.");
981c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            tracker.onFailed(mContext, RESULT_ERROR_NO_SERVICE, 0/*errorCode*/);
9820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
9830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (pdu == null) {
986c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            Rlog.e(TAG, "Empty PDU");
987c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            tracker.onFailed(mContext, RESULT_ERROR_NULL_PDU, 0/*errorCode*/);
9880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
9890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Get calling app package name via UID from Binder call
9920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        PackageManager pm = mContext.getPackageManager();
9930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String[] packageNames = pm.getPackagesForUid(Binder.getCallingUid());
9940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (packageNames == null || packageNames.length == 0) {
9960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Refuse to send SMS if we can't get the calling package name.
997ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(TAG, "Can't get calling app package name: refusing to send SMS");
998c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/);
9990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
10000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
10010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10022029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra        // Get package info via packagemanager
10030d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        PackageInfo appInfo;
10042029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra        try {
10052029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra            // XXX this is lossy- apps can share a UID
100632cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak            appInfo = pm.getPackageInfoAsUser(
100732cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak                    packageNames[0], PackageManager.GET_SIGNATURES, tracker.mUserId);
10082029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra        } catch (PackageManager.NameNotFoundException e) {
1009ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(TAG, "Can't get calling app package info: refusing to send SMS");
1010c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/);
10112029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra            return;
10122029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra        }
10130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // checkDestination() returns true if the destination is not a premium short code or the
10150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // sending app is approved to send to short codes. Otherwise, a message is sent to our
10160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // handler with the SmsTracker to request user confirmation before sending.
10170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (checkDestination(tracker)) {
10180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // check for excessive outgoing SMS usage by this app
10192029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra            if (!mUsageMonitor.check(appInfo.packageName, SINGLE_PART_SMS)) {
10200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, tracker));
10210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return;
10220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
10230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1024a0c22039b77054d659151537896c1db90c7057f7Shishir Agrawal            sendSms(tracker);
10250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
10265eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry
10275eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry        if (PhoneNumberUtils.isLocalEmergencyNumber(mContext, tracker.mDestAddress)) {
10285eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry            new AsyncEmergencyContactNotifier(mContext).execute();
10295eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry        }
10300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
10310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
10320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
10330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Check if destination is a potential premium short code and sender is not pre-approved to
10340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * send to short codes.
10350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
10360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param tracker the tracker for the SMS to send
10370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return true if the destination is approved; false if user confirmation event was sent
10380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
10390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    boolean checkDestination(SmsTracker tracker) {
1040bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan        if (mContext.checkCallingOrSelfPermission(SEND_SMS_NO_CONFIRMATION)
1041bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                == PackageManager.PERMISSION_GRANTED) {
1042bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            return true;            // app is pre-approved to send to short codes
1043bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan        } else {
1044bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            int rule = mPremiumSmsRule.get();
1045bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            int smsCategory = SmsUsageMonitor.CATEGORY_NOT_SHORT_CODE;
1046bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            if (rule == PREMIUM_RULE_USE_SIM || rule == PREMIUM_RULE_USE_BOTH) {
1047bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                String simCountryIso = mTelephonyManager.getSimCountryIso();
1048bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                if (simCountryIso == null || simCountryIso.length() != 2) {
1049bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    Rlog.e(TAG, "Can't get SIM country Iso: trying network country Iso");
1050bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    simCountryIso = mTelephonyManager.getNetworkCountryIso();
1051bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                }
1052ee7b6094d4f3d4c641e54246aec8f61349d6e9d0Robert Greenwalt
1053bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                smsCategory = mUsageMonitor.checkDestination(tracker.mDestAddress, simCountryIso);
10540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1055bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            if (rule == PREMIUM_RULE_USE_NETWORK || rule == PREMIUM_RULE_USE_BOTH) {
1056bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                String networkCountryIso = mTelephonyManager.getNetworkCountryIso();
1057bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                if (networkCountryIso == null || networkCountryIso.length() != 2) {
1058bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    Rlog.e(TAG, "Can't get Network country Iso: trying SIM country Iso");
1059bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    networkCountryIso = mTelephonyManager.getSimCountryIso();
1060bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                }
10610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1062bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                smsCategory = SmsUsageMonitor.mergeShortCodeCategories(smsCategory,
1063bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                        mUsageMonitor.checkDestination(tracker.mDestAddress, networkCountryIso));
1064bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            }
10654658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
1066bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            if (smsCategory == SmsUsageMonitor.CATEGORY_NOT_SHORT_CODE
1067bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    || smsCategory == SmsUsageMonitor.CATEGORY_FREE_SHORT_CODE
1068bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    || smsCategory == SmsUsageMonitor.CATEGORY_STANDARD_SHORT_CODE) {
1069bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                return true;    // not a premium short code
1070bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            }
10710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
107215f55ca2f204e664807e047b5f898693b274bab6fionaxu            // Do not allow any premium sms during SuW
107315f55ca2f204e664807e047b5f898693b274bab6fionaxu            if (Settings.Global.getInt(mResolver, Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
107415f55ca2f204e664807e047b5f898693b274bab6fionaxu                Rlog.e(TAG, "Can't send premium sms during Setup Wizard");
107515f55ca2f204e664807e047b5f898693b274bab6fionaxu                return false;
107615f55ca2f204e664807e047b5f898693b274bab6fionaxu            }
107715f55ca2f204e664807e047b5f898693b274bab6fionaxu
1078bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            // Wait for user confirmation unless the user has set permission to always allow/deny
1079bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            int premiumSmsPermission = mUsageMonitor.getPremiumSmsPermission(
1080ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian                    tracker.getAppPackageName());
1081bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            if (premiumSmsPermission == SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) {
1082bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                // First time trying to send to premium SMS.
1083bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                premiumSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER;
1084bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            }
1085d1e1ef20799b3d6290523b613b5189dd3fe4812fAmit Mahajan
1086bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            switch (premiumSmsPermission) {
1087bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW:
1088bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    Rlog.d(TAG, "User approved this app to send to premium SMS");
1089bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    return true;
1090bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan
1091bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW:
1092bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    Rlog.w(TAG, "User denied this app from sending to premium SMS");
1093d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                    Message msg = obtainMessage(EVENT_STOP_SENDING, tracker);
1094d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                    msg.arg1 = ConfirmDialogListener.SHORT_CODE_MSG;
1095d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                    msg.arg2 = ConfirmDialogListener.NEVER_ALLOW;
1096d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                    sendMessage(msg);
1097bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    return false;   // reject this message
1098bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan
1099bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER:
1100bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                default:
1101bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    int event;
1102bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    if (smsCategory == SmsUsageMonitor.CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE) {
1103bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                        event = EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE;
1104bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    } else {
1105bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                        event = EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE;
1106bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    }
1107bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    sendMessage(obtainMessage(event, tracker));
1108bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan                    return false;   // wait for user confirmation
1109bd5e7244c02d3af32ac260d6d240006a49b3a694Amit Mahajan            }
11100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
11110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
11120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
11140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Deny sending an SMS if the outgoing queue limit is reached. Used when the message
11150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * must be confirmed by the user due to excessive usage or potential premium SMS detected.
11160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param tracker the SmsTracker for the message to send
11170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return true if the message was denied; false to continue with send confirmation
11180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
11190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean denyIfQueueLimitReached(SmsTracker tracker) {
11200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mPendingTrackerCount >= MO_MSG_QUEUE_LIMIT) {
11210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Deny sending message when the queue limit is reached.
1122c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            Rlog.e(TAG, "Denied because queue limit reached");
1123c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            tracker.onFailed(mContext, RESULT_ERROR_LIMIT_EXCEEDED, 0/*errorCode*/);
11240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return true;
11250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
11260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mPendingTrackerCount++;
11270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return false;
11280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
11290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
11310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Returns the label for the specified app package name.
11320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param appPackage the package name of the app requesting to send an SMS
11330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return the label for the specified app, or the package name if getApplicationInfo() fails
11340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
113532cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak    private CharSequence getAppLabel(String appPackage, @UserIdInt int userId) {
11360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        PackageManager pm = mContext.getPackageManager();
11370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
113832cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak            ApplicationInfo appInfo = pm.getApplicationInfoAsUser(appPackage, 0, userId);
11392eca414f1c7641c5b8069a09f191de7ebe692045fionaxu            return appInfo.loadSafeLabel(pm);
11400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (PackageManager.NameNotFoundException e) {
1141ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.e(TAG, "PackageManager Name Not Found for package " + appPackage);
11420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return appPackage;  // fall back to package name if we can't get app label
11430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
11440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
11450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
11470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Post an alert when SMS needs confirmation due to excessive usage.
11480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param tracker an SmsTracker for the current message.
11490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
11500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void handleReachSentLimit(SmsTracker tracker) {
11510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (denyIfQueueLimitReached(tracker)) {
11520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;     // queue limit reached; error was returned to caller
11530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
11540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1155ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian        CharSequence appLabel = getAppLabel(tracker.getAppPackageName(), tracker.mUserId);
11560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Resources r = Resources.getSystem();
11570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Spanned messageText = Html.fromHtml(r.getString(R.string.sms_control_message, appLabel));
11580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1159d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian        // Construct ConfirmDialogListenter for Rate Limit handling
1160d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian        ConfirmDialogListener listener = new ConfirmDialogListener(tracker, null,
1161d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                ConfirmDialogListener.RATE_LIMIT);
11620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        AlertDialog d = new AlertDialog.Builder(mContext)
11640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                .setTitle(R.string.sms_control_title)
11650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                .setIcon(R.drawable.stat_sys_warning)
11660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                .setMessage(messageText)
11670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                .setPositiveButton(r.getString(R.string.sms_control_yes), listener)
11680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                .setNegativeButton(r.getString(R.string.sms_control_no), listener)
11690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                .setOnCancelListener(listener)
11700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                .create();
11710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
11730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        d.show();
11740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
11750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
11770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Post an alert for user confirmation when sending to a potential short code.
11780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param isPremium true if the destination is known to be a premium short code
11790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param tracker the SmsTracker for the current message.
11800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
11810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void handleConfirmShortCode(boolean isPremium, SmsTracker tracker) {
11820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (denyIfQueueLimitReached(tracker)) {
11830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;     // queue limit reached; error was returned to caller
11840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
11850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11864658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        int detailsId;
11870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (isPremium) {
11884658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            detailsId = R.string.sms_premium_short_code_details;
11890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
11904658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            detailsId = R.string.sms_short_code_details;
11910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
11920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1193ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian        CharSequence appLabel = getAppLabel(tracker.getAppPackageName(), tracker.mUserId);
11940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Resources r = Resources.getSystem();
11954658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        Spanned messageText = Html.fromHtml(r.getString(R.string.sms_short_code_confirm_message,
11964658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                appLabel, tracker.mDestAddress));
11970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
11984658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
11994658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                Context.LAYOUT_INFLATER_SERVICE);
12004658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        View layout = inflater.inflate(R.layout.sms_short_code_confirmation_dialog, null);
12014658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
1202d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian        // Construct ConfirmDialogListenter for short code message sending
120378df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt        ConfirmDialogListener listener = new ConfirmDialogListener(tracker,
1204d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                (TextView) layout.findViewById(R.id.sms_short_code_remember_undo_instruction),
1205d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                ConfirmDialogListener.SHORT_CODE_MSG);
120678df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt
120778df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt
12084658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        TextView messageView = (TextView) layout.findViewById(R.id.sms_short_code_confirm_message);
12094658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        messageView.setText(messageText);
12104658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
121178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt        ViewGroup detailsLayout = (ViewGroup) layout.findViewById(
12124658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                R.id.sms_short_code_detail_layout);
12134658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        TextView detailsView = (TextView) detailsLayout.findViewById(
12144658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                R.id.sms_short_code_detail_message);
12154658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        detailsView.setText(detailsId);
12164658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
12174658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        CheckBox rememberChoice = (CheckBox) layout.findViewById(
12184658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                R.id.sms_short_code_remember_choice_checkbox);
12194658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        rememberChoice.setOnCheckedChangeListener(listener);
12204658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
12210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        AlertDialog d = new AlertDialog.Builder(mContext)
12224658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                .setView(layout)
12230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                .setPositiveButton(r.getString(R.string.sms_short_code_confirm_allow), listener)
12240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                .setNegativeButton(r.getString(R.string.sms_short_code_confirm_deny), listener)
12250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                .setOnCancelListener(listener)
12260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                .create();
12270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
12290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        d.show();
12304658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
12314658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        listener.setPositiveButton(d.getButton(DialogInterface.BUTTON_POSITIVE));
12324658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        listener.setNegativeButton(d.getButton(DialogInterface.BUTTON_NEGATIVE));
12334658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby    }
12344658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
12354658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby    /**
12364658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     * Returns the premium SMS permission for the specified package. If the package has never
12374658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     * been seen before, the default {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER}
12384658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     * will be returned.
12394658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     * @param packageName the name of the package to query permission
12404658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     * @return one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_UNKNOWN},
12414658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     *  {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER},
12424658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     *  {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or
12434658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     *  {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW}
12444658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     */
12454658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby    public int getPremiumSmsPermission(String packageName) {
12464658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        return mUsageMonitor.getPremiumSmsPermission(packageName);
12474658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby    }
12484658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
12494658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby    /**
12504658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     * Sets the premium SMS permission for the specified package and save the value asynchronously
12514658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     * to persistent storage.
12524658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     * @param packageName the name of the package to set permission
12534658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     * @param permission one of {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ASK_USER},
12544658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     *  {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_NEVER_ALLOW}, or
12554658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     *  {@link SmsUsageMonitor#PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW}
12564658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby     */
12574658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby    public void setPremiumSmsPermission(String packageName, int permission) {
12584658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        mUsageMonitor.setPremiumSmsPermission(packageName, permission);
12590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
12600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
12620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Send the message along to the radio.
12630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
12640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param tracker holds the SMS message to send
12650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
12660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected abstract void sendSms(SmsTracker tracker);
12670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
12698d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang     * Send the SMS via the PSTN network.
12708d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang     *
12718d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang     * @param tracker holds the Sms tracker ready to be sent
12728d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang     */
12738d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    protected abstract void sendSmsByPstn(SmsTracker tracker);
12748d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang
12758d8e8f45200d17b78d196d8cba389fd9c547ac11Cheuksan Wang    /**
12761260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * Retry the message along to the radio.
12771260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     *
12781260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * @param tracker holds the SMS message to send
12791260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     */
1280ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa    public void sendRetrySms(SmsTracker tracker) {
1281ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        // re-routing to ImsSMSDispatcher
1282ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        if (mImsSMSDispatcher != null) {
1283ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            mImsSMSDispatcher.sendRetrySms(tracker);
1284ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        } else {
1285ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            Rlog.e(TAG, mImsSMSDispatcher + " is null. Retry failed");
1286ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        }
1287ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa    }
12881260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
12891260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    /**
12900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Send the multi-part SMS based on multipart Sms tracker
12910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
12920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param tracker holds the multipart Sms tracker ready to be sent
12930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
12940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void sendMultipartSms(SmsTracker tracker) {
12950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ArrayList<String> parts;
12960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ArrayList<PendingIntent> sentIntents;
12970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ArrayList<PendingIntent> deliveryIntents;
12980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
12995d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan        HashMap<String, Object> map = tracker.getData();
13000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String destinationAddress = (String) map.get("destination");
13020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String scAddress = (String) map.get("scaddress");
13030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        parts = (ArrayList<String>) map.get("parts");
13050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        sentIntents = (ArrayList<PendingIntent>) map.get("sentIntents");
13060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        deliveryIntents = (ArrayList<PendingIntent>) map.get("deliveryIntents");
13070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // check if in service
13090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int ss = mPhone.getServiceState().getState();
13101260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        // if sms over IMS is not supported on data and voice is not available...
13111260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
13120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (int i = 0, count = parts.size(); i < count; i++) {
13130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                PendingIntent sentIntent = null;
13140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (sentIntents != null && sentIntents.size() > i) {
13150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    sentIntent = sentIntents.get(i);
13160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
13170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                handleNotInService(ss, sentIntent);
13180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
13190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
13200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
13210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1322b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen        sendMultipartText(destinationAddress, scAddress, parts, sentIntents, deliveryIntents,
1323a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                null/*messageUri*/, null/*callingPkg*/, tracker.mPersistMessage);
13240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
13250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
13270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Keeps track of an SMS that has been sent to the RIL, until it has
13280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * successfully been sent, or we're done trying.
13290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
13305d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan    public static class SmsTracker {
13310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // fields need to be public for derived SmsDispatchers
13325d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan        private final HashMap<String, Object> mData;
13330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public int mRetryCount;
13341260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        public int mImsRetry; // nonzero indicates initial message was sent over Ims
13350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public int mMessageRef;
13366ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi        public boolean mExpectMore;
13371260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        String mFormat;
13380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public final PendingIntent mSentIntent;
13400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public final PendingIntent mDeliveryIntent;
13410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13422029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra        public final PackageInfo mAppInfo;
13430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public final String mDestAddress;
13440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
134578d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal        public final SmsHeader mSmsHeader;
134678d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal
13470217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun        private long mTimestamp = System.currentTimeMillis();
1348c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        public Uri mMessageUri; // Uri of persisted message if we wrote one
1349c99dab56e20222b28cbc6238645feac938f1c333Ye Wen
1350c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        // Reference to states of a multipart message that this part belongs to
1351c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        private AtomicInteger mUnsentPartCount;
1352c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        private AtomicBoolean mAnyPartFailed;
13534bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen        // The full message content of a single part message
13544bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen        // or a multipart message that this part belongs to
13554bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen        private String mFullMessageText;
13564bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen
13574bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen        private int mSubId;
13580217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun
135952a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen        // If this is a text message (instead of data message)
136052a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen        private boolean mIsText;
136152a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen
1362a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang        private boolean mPersistMessage;
1363a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang
136432cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak        // User who sends the SMS.
136532cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak        private final @UserIdInt int mUserId;
136632cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak
13671260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        private SmsTracker(HashMap<String, Object> data, PendingIntent sentIntent,
1368c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                PendingIntent deliveryIntent, PackageInfo appInfo, String destAddr, String format,
136978d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal                AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
137052a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen                SmsHeader smsHeader, boolean isExpectMore, String fullMessageText, int subId,
137132cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak                boolean isText, boolean persistMessage, int userId) {
13720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mData = data;
13730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mSentIntent = sentIntent;
13740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mDeliveryIntent = deliveryIntent;
13750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mRetryCount = 0;
13762029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra            mAppInfo = appInfo;
13770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mDestAddress = destAddr;
13781260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            mFormat = format;
13796ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi            mExpectMore = isExpectMore;
13801260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            mImsRetry = 0;
13811260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            mMessageRef = 0;
1382c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            mUnsentPartCount = unsentPartCount;
1383c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            mAnyPartFailed = anyPartFailed;
1384c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            mMessageUri = messageUri;
138578d39a9fab86a26f4f39585af5cfe2a07c756fceShishir Agrawal            mSmsHeader = smsHeader;
13864bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            mFullMessageText = fullMessageText;
13874bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            mSubId = subId;
138852a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen            mIsText = isText;
1389a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            mPersistMessage = persistMessage;
139032cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak            mUserId = userId;
13910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
13920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
13930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        /**
13940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * Returns whether this tracker holds a multi-part SMS.
13950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         * @return true if the tracker holds a multi-part SMS; false otherwise
13960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville         */
13970d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        boolean isMultipart() {
13980217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun            return mData.containsKey("parts");
13990217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun        }
14000217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun
14015d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan        public HashMap<String, Object> getData() {
14025d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan            return mData;
14035d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan        }
14045d5ca33a24e6b73a48b575a0e1a5e790784d0bb7Amit Mahajan
14050217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun        /**
1406ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian         * Get the App package name
1407ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian         * @return App package name info
1408ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian         */
1409ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian        public String getAppPackageName() {
1410ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian            return mAppInfo != null ? mAppInfo.packageName : null;
1411ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian        }
1412ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian
1413ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian        /**
14140217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun         * Update the status of this message if we persisted it
14150217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun         */
14160217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun        public void updateSentMessageStatus(Context context, int status) {
1417c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            if (mMessageUri != null) {
14180217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun                // If we wrote this message in writeSentMessage, update it now
14190217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun                ContentValues values = new ContentValues(1);
14200217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun                values.put(Sms.STATUS, status);
14210217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun                SqliteWrapper.update(context, context.getContentResolver(),
1422c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                        mMessageUri, values, null, null);
1423c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            }
1424c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        }
1425c99dab56e20222b28cbc6238645feac938f1c333Ye Wen
1426c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        /**
14274bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen         * Set the final state of a message: FAILED or SENT
1428c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         *
1429c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         * @param context The Context
14304bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen         * @param messageType The final message type
1431c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         * @param errorCode The error code
1432c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         */
14334bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen        private void updateMessageState(Context context, int messageType, int errorCode) {
1434c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            if (mMessageUri == null) {
1435c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                return;
1436c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            }
14374bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            final ContentValues values = new ContentValues(2);
14384bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            values.put(Sms.TYPE, messageType);
1439c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            values.put(Sms.ERROR_CODE, errorCode);
1440c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            final long identity = Binder.clearCallingIdentity();
1441c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            try {
1442c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                if (SqliteWrapper.update(context, context.getContentResolver(), mMessageUri, values,
1443c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                        null/*where*/, null/*selectionArgs*/) != 1) {
14444bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    Rlog.e(TAG, "Failed to move message to " + messageType);
1445c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                }
1446c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            } finally {
1447c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                Binder.restoreCallingIdentity(identity);
1448c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            }
1449c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        }
1450c99dab56e20222b28cbc6238645feac938f1c333Ye Wen
1451c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        /**
145252a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen         * Persist a sent SMS if required:
145352a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen         * 1. It is a text message
145452a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen         * 2. SmsApplication tells us to persist: sent from apps that are not default-SMS app or
145552a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen         *    bluetooth
1456c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         *
14574bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen         * @param context
14584bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen         * @param messageType The folder to store (FAILED or SENT)
14594bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen         * @param errorCode The current error code for this SMS or SMS part
14604bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen         * @return The telephony provider URI if stored
1461c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         */
14624bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen        private Uri persistSentMessageIfRequired(Context context, int messageType, int errorCode) {
1463a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            if (!mIsText || !mPersistMessage ||
146452a98d0a37731f48a316bc79fbc2c5a0f00a5e58Ye Wen                    !SmsApplication.shouldWriteMessageForPackage(mAppInfo.packageName, context)) {
14654bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                return null;
14664bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            }
14674bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            Rlog.d(TAG, "Persist SMS into "
14684bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    + (messageType == Sms.MESSAGE_TYPE_FAILED ? "FAILED" : "SENT"));
14694bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            final ContentValues values = new ContentValues();
14704b09dff383ae7dfca595aeeea886a594a1947340Wink Saville            values.put(Sms.SUBSCRIPTION_ID, mSubId);
14714bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            values.put(Sms.ADDRESS, mDestAddress);
14724bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            values.put(Sms.BODY, mFullMessageText);
14734bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            values.put(Sms.DATE, System.currentTimeMillis()); // milliseconds
14744bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            values.put(Sms.SEEN, 1);
14754bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            values.put(Sms.READ, 1);
14764bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            final String creator = mAppInfo != null ? mAppInfo.packageName : null;
14774bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            if (!TextUtils.isEmpty(creator)) {
14784bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                values.put(Sms.CREATOR, creator);
14794bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            }
14804bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            if (mDeliveryIntent != null) {
14814bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                values.put(Sms.STATUS, Telephony.Sms.STATUS_PENDING);
14824bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            }
14834bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            if (errorCode != 0) {
14844bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                values.put(Sms.ERROR_CODE, errorCode);
1485c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            }
1486c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            final long identity = Binder.clearCallingIdentity();
14874bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            final ContentResolver resolver = context.getContentResolver();
1488c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            try {
14894bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                final Uri uri =  resolver.insert(Telephony.Sms.Sent.CONTENT_URI, values);
14904bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                if (uri != null && messageType == Sms.MESSAGE_TYPE_FAILED) {
14914bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    // Since we can't persist a message directly into FAILED box,
14924bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    // we have to update the column after we persist it into SENT box.
14934bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    // The gap between the state change is tiny so I would not expect
14944bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    // it to cause any serious problem
14954bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    // TODO: we should add a "failed" URI for this in SmsProvider?
14964bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    final ContentValues updateValues = new ContentValues(1);
14974bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    updateValues.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED);
14984bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    resolver.update(uri, updateValues, null/*where*/, null/*selectionArgs*/);
1499c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                }
15004bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                return uri;
15014bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            } catch (Exception e) {
15024bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                Rlog.e(TAG, "writeOutboxMessage: Failed to persist outbox message", e);
15034bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                return null;
1504c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            } finally {
1505c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                Binder.restoreCallingIdentity(identity);
1506c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            }
1507c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        }
1508c99dab56e20222b28cbc6238645feac938f1c333Ye Wen
1509c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        /**
15104bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen         * Persist or update an SMS depending on if we send a new message or a stored message
15114bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen         *
15124bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen         * @param context
15134bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen         * @param messageType The message folder for this SMS, FAILED or SENT
15144bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen         * @param errorCode The current error code for this SMS or SMS part
15154bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen         */
15164bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen        private void persistOrUpdateMessage(Context context, int messageType, int errorCode) {
15174bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            if (mMessageUri != null) {
15184bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                updateMessageState(context, messageType, errorCode);
15194bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            } else {
15204bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                mMessageUri = persistSentMessageIfRequired(context, messageType, errorCode);
15214bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            }
15224bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen        }
15234bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen
15244bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen        /**
1525c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         * Handle a failure of a single part message or a part of a multipart message
1526c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         *
1527c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         * @param context The Context
1528c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         * @param error The error to send back with
1529c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         * @param errorCode
1530c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         */
1531c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        public void onFailed(Context context, int error, int errorCode) {
1532c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            if (mAnyPartFailed != null) {
1533c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                mAnyPartFailed.set(true);
1534c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            }
1535c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            // is single part or last part of multipart message
1536c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            boolean isSinglePartOrLastPart = true;
1537c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            if (mUnsentPartCount != null) {
1538c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0;
1539c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            }
1540c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            if (isSinglePartOrLastPart) {
15414bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                persistOrUpdateMessage(context, Sms.MESSAGE_TYPE_FAILED, errorCode);
1542c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            }
1543c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            if (mSentIntent != null) {
1544c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                try {
1545fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                    // Extra information to send with the sent intent
1546fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                    Intent fillIn = new Intent();
1547fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                    if (mMessageUri != null) {
1548fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                        // Pass this to SMS apps so that they know where it is stored
1549fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                        fillIn.putExtra("uri", mMessageUri.toString());
1550fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                    }
1551c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    if (errorCode != 0) {
1552c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                        fillIn.putExtra("errorCode", errorCode);
1553c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    }
1554c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    if (mUnsentPartCount != null && isSinglePartOrLastPart) {
1555c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                        // Is multipart and last part
1556c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                        fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true);
1557c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    }
1558c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    mSentIntent.send(context, error, fillIn);
1559c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                } catch (CanceledException ex) {
1560c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    Rlog.e(TAG, "Failed to send result");
1561c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                }
1562c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            }
1563c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        }
1564c99dab56e20222b28cbc6238645feac938f1c333Ye Wen
1565c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        /**
1566c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         * Handle the sent of a single part message or a part of a multipart message
1567c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         *
1568c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         * @param context The Context
1569c99dab56e20222b28cbc6238645feac938f1c333Ye Wen         */
1570c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        public void onSent(Context context) {
1571c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            // is single part or last part of multipart message
1572c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            boolean isSinglePartOrLastPart = true;
1573c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            if (mUnsentPartCount != null) {
1574c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0;
1575c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            }
1576c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            if (isSinglePartOrLastPart) {
15774bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                int messageType = Sms.MESSAGE_TYPE_SENT;
1578c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                if (mAnyPartFailed != null && mAnyPartFailed.get()) {
15794bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                    messageType = Sms.MESSAGE_TYPE_FAILED;
1580c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                }
15814bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                persistOrUpdateMessage(context, messageType, 0/*errorCode*/);
1582c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            }
1583c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            if (mSentIntent != null) {
1584c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                try {
1585fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                    // Extra information to send with the sent intent
1586fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                    Intent fillIn = new Intent();
1587fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                    if (mMessageUri != null) {
1588fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                        // Pass this to SMS apps so that they know where it is stored
1589fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                        fillIn.putExtra("uri", mMessageUri.toString());
1590fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                    }
1591c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    if (mUnsentPartCount != null && isSinglePartOrLastPart) {
1592c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                        // Is multipart and last part
1593fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                        fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true);
1594c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    }
1595fce79caf5d7628cde43c5f0cd3d369673bc15212Ye Wen                    mSentIntent.send(context, Activity.RESULT_OK, fillIn);
1596c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                } catch (CanceledException ex) {
1597c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                    Rlog.e(TAG, "Failed to send result");
1598c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                }
15990217e2d6e60f7edd95407c7b385a627da9f1c1e3David Braun            }
16000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
16010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
16020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1603ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa    protected SmsTracker getSmsTracker(HashMap<String, Object> data, PendingIntent sentIntent,
1604c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            PendingIntent deliveryIntent, String format, AtomicInteger unsentPartCount,
16056ad88a8a2caf739e78c8d5f7f50fc7fa84a07ca7Chaitanya Saggurthi            AtomicBoolean anyPartFailed, Uri messageUri, SmsHeader smsHeader,
1606a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            boolean isExpectMore, String fullMessageText, boolean isText, boolean persistMessage) {
16071260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        // Get calling app package name via UID from Binder call
16081260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        PackageManager pm = mContext.getPackageManager();
16091260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        String[] packageNames = pm.getPackagesForUid(Binder.getCallingUid());
16101260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
16111260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        // Get package info via packagemanager
161232cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak        final int userId = UserHandle.getCallingUserId();
16131260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        PackageInfo appInfo = null;
16141260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        if (packageNames != null && packageNames.length > 0) {
16151260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            try {
16161260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                // XXX this is lossy- apps can share a UID
161732cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak                appInfo = pm.getPackageInfoAsUser(
161832cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak                        packageNames[0], PackageManager.GET_SIGNATURES, userId);
16191260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            } catch (PackageManager.NameNotFoundException e) {
16201260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                // error will be logged in sendRawPdu
16211260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
16221260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        }
16231260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        // Strip non-digits from destination phone number before checking for short codes
16241260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        // and before displaying the number to the user if confirmation is required.
16251260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        String destAddr = PhoneNumberUtils.extractNetworkPortion((String) data.get("destAddr"));
1626c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        return new SmsTracker(data, sentIntent, deliveryIntent, appInfo, destAddr, format,
16274bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                unsentPartCount, anyPartFailed, messageUri, smsHeader, isExpectMore,
162832cc74b9ec7397e995f4e2275315c6f79d1e43fdTony Mak                fullMessageText, getSubId(), isText, persistMessage, userId);
1629c99dab56e20222b28cbc6238645feac938f1c333Ye Wen    }
1630c99dab56e20222b28cbc6238645feac938f1c333Ye Wen
1631c99dab56e20222b28cbc6238645feac938f1c333Ye Wen    protected SmsTracker getSmsTracker(HashMap<String, Object> data, PendingIntent sentIntent,
16324bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen            PendingIntent deliveryIntent, String format, Uri messageUri, boolean isExpectMore,
1633a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang            String fullMessageText, boolean isText, boolean persistMessage) {
1634c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        return getSmsTracker(data, sentIntent, deliveryIntent, format, null/*unsentPartCount*/,
16354bd1dec4138ac11a91a8ec606a27fc4c5c63f14bYe Wen                null/*anyPartFailed*/, messageUri, null/*smsHeader*/, isExpectMore,
1636a8f8c5a113a66de4854f4fb13a5825eb0705bd59Ji Yang                fullMessageText, isText, persistMessage);
16371260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
16381260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
1639ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa    protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
16401260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            String text, SmsMessageBase.SubmitPduBase pdu) {
16411260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        HashMap<String, Object> map = new HashMap<String, Object>();
16421260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        map.put("destAddr", destAddr);
16431260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        map.put("scAddr", scAddr);
16441260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        map.put("text", text);
16451260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        map.put("smsc", pdu.encodedScAddress);
16461260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        map.put("pdu", pdu.encodedMessage);
16471260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        return map;
16481260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
16491260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
1650ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa    protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
16511260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu) {
16521260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        HashMap<String, Object> map = new HashMap<String, Object>();
16531260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        map.put("destAddr", destAddr);
16541260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        map.put("scAddr", scAddr);
1655ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        map.put("destPort", destPort);
16561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        map.put("data", data);
16571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        map.put("smsc", pdu.encodedScAddress);
16581260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        map.put("pdu", pdu.encodedMessage);
16591260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        return map;
16601260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
16611260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
16620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
16630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Dialog listener for SMS confirmation dialog.
16640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
16650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final class ConfirmDialogListener
16664658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener,
16674658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            CompoundButton.OnCheckedChangeListener {
16680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        private final SmsTracker mTracker;
16704658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        private Button mPositiveButton;
16714658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        private Button mNegativeButton;
16724658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        private boolean mRememberChoice;    // default is unchecked
167378df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt        private final TextView mRememberUndoInstruction;
1674d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian        private int mConfirmationType;  // 0 - Short Code Msg Sending; 1 - Rate Limit Exceeded
1675d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian        private static final int SHORT_CODE_MSG = 0; // Short Code Msg
1676d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian        private static final int RATE_LIMIT = 1; // Rate Limit Exceeded
1677d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian        private static final int NEVER_ALLOW = 1; // Never Allow
16780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1679d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian        ConfirmDialogListener(SmsTracker tracker, TextView textView, int confirmationType) {
16800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mTracker = tracker;
168178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt            mRememberUndoInstruction = textView;
1682d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian            mConfirmationType = confirmationType;
16830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
16840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
16854658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        void setPositiveButton(Button button) {
16864658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            mPositiveButton = button;
16874658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        }
16884658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
16894658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        void setNegativeButton(Button button) {
16904658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            mNegativeButton = button;
16914658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        }
16924658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
16930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        @Override
16940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public void onClick(DialogInterface dialog, int which) {
16954658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            // Always set the SMS permission so that Settings will show a permission setting
16964658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            // for the app (it won't be shown until after the app tries to send to a short code).
16974658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            int newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER;
16984658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
16990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (which == DialogInterface.BUTTON_POSITIVE) {
1700ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(TAG, "CONFIRM sending SMS");
17012029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra                // XXX this is lossy- apps can have more than one signature
1702634a24f56f54b5d2911649288147c750b67c7ae4William Luh                EventLog.writeEvent(EventLogTags.EXP_DET_SMS_SENT_BY_USER,
1703ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh                                    mTracker.mAppInfo.applicationInfo == null ?
1704ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh                                    -1 : mTracker.mAppInfo.applicationInfo.uid);
17050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sendMessage(obtainMessage(EVENT_SEND_CONFIRMED_SMS, mTracker));
17064658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                if (mRememberChoice) {
17074658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                    newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW;
17084658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                }
17090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (which == DialogInterface.BUTTON_NEGATIVE) {
1710ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(TAG, "DENY sending SMS");
17112029d86b5aebd03f7acbd249a4e2e4f65ec37d47Geremy Condra                // XXX this is lossy- apps can have more than one signature
1712634a24f56f54b5d2911649288147c750b67c7ae4William Luh                EventLog.writeEvent(EventLogTags.EXP_DET_SMS_DENIED_BY_USER,
1713ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh                                    mTracker.mAppInfo.applicationInfo == null ?
1714ec125af4306f1be2c829c3a1d7adbf9b8cd7e659William Luh                                    -1 :  mTracker.mAppInfo.applicationInfo.uid);
1715d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                Message msg = obtainMessage(EVENT_STOP_SENDING, mTracker);
1716d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                msg.arg1 = mConfirmationType;
17174658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                if (mRememberChoice) {
17184658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                    newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW;
1719d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                    msg.arg2 = ConfirmDialogListener.NEVER_ALLOW;
17204658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                }
1721d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian                sendMessage(msg);
17220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1723ba3b8c9ebd8e36da54ce0fec81c6ea5f460aa51esqian            setPremiumSmsPermission(mTracker.getAppPackageName(), newSmsPermission);
17240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
17250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
17260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        @Override
17270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public void onCancel(DialogInterface dialog) {
1728ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.d(TAG, "dialog dismissed: don't send SMS");
1729d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian            Message msg = obtainMessage(EVENT_STOP_SENDING, mTracker);
1730d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian            msg.arg1 = mConfirmationType;
1731d9be5fb196cc153aa4f27ef7a4a6b3a561ee8229sqian            sendMessage(msg);
17320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
17334658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby
17344658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        @Override
17354658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1736ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.d(TAG, "remember this choice: " + isChecked);
17374658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            mRememberChoice = isChecked;
17384658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            if (isChecked) {
17394658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                mPositiveButton.setText(R.string.sms_short_code_confirm_always_allow);
17404658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                mNegativeButton.setText(R.string.sms_short_code_confirm_never_allow);
174178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt                if (mRememberUndoInstruction != null) {
174278df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt                    mRememberUndoInstruction.
174378df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt                            setText(R.string.sms_short_code_remember_undo_instruction);
174478df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt                    mRememberUndoInstruction.setPadding(0,0,0,32);
174578df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt                }
17464658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            } else {
17474658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby                mPositiveButton.setText(R.string.sms_short_code_confirm_allow);
17485d875796122cdd8a7004e8e3964b20b5c65a31a1Robert Greenwalt                mNegativeButton.setText(R.string.sms_short_code_confirm_deny);
174978df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt                if (mRememberUndoInstruction != null) {
175078df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt                    mRememberUndoInstruction.setText("");
175178df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt                    mRememberUndoInstruction.setPadding(0,0,0,0);
175278df2f47241a498bbd919c4c19a44b824e5dc2d6Robert Greenwalt                }
17534658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby            }
17544658a1a8c23111d5cc89feb040ce547a7b65dfb0Jake Hamby        }
17550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
17561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
1757ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa    public boolean isIms() {
1758ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        if (mImsSMSDispatcher != null) {
1759ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            return mImsSMSDispatcher.isIms();
1760ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        } else {
1761ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            Rlog.e(TAG, mImsSMSDispatcher + " is null");
1762ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            return false;
1763ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        }
1764ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa    }
17651260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
1766ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa    public String getImsSmsFormat() {
1767ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        if (mImsSMSDispatcher != null) {
1768ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            return mImsSMSDispatcher.getImsSmsFormat();
1769ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        } else {
1770ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            Rlog.e(TAG, mImsSMSDispatcher + " is null");
1771ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa            return null;
1772ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa        }
1773ace9a749c5a2a5e07527f728b7331423d16c36cdSukanya Rajkhowa    }
1774c99dab56e20222b28cbc6238645feac938f1c333Ye Wen
1775c99dab56e20222b28cbc6238645feac938f1c333Ye Wen    private String getMultipartMessageText(ArrayList<String> parts) {
1776c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        final StringBuilder sb = new StringBuilder();
1777c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        for (String part : parts) {
1778c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            if (part != null) {
1779c99dab56e20222b28cbc6238645feac938f1c333Ye Wen                sb.append(part);
1780c99dab56e20222b28cbc6238645feac938f1c333Ye Wen            }
1781c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        }
1782c99dab56e20222b28cbc6238645feac938f1c333Ye Wen        return sb.toString();
1783c99dab56e20222b28cbc6238645feac938f1c333Ye Wen    }
1784b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen
17858215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang    protected String getCarrierAppPackageName() {
1786062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
17877f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal        if (card == null) {
17887f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal            return null;
17897f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal        }
17907f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal
1791934a24a6aa2b7a981e872fa350648904ed80280aDiego Pontoriero        List<String> carrierPackages = card.getCarrierPackageNamesForIntent(
17928215559cd1141ac90c478fd3df75e43c9d755c6cCheuksan Wang            mContext.getPackageManager(), new Intent(CarrierMessagingService.SERVICE_INTERFACE));
17934256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala        if (carrierPackages != null && carrierPackages.size() == 1) {
17944256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala            return carrierPackages.get(0);
17954256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala        }
17964256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala        // If there is no carrier package which implements CarrierMessagingService, then lookup if
17974256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala        // for a carrierImsPackage that implements CarrierMessagingService.
17984256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala        return CarrierSmsUtils.getCarrierImsPackageForIntent(mContext, mPhone,
17994256e499c8e1e0a07998dcaf1f3aa127b693fc42Madhusudhan R. Adupala                new Intent(CarrierMessagingService.SERVICE_INTERFACE));
1800c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    }
1801c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal
1802b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville    protected int getSubId() {
180314bdfdca7a5412edf5fbdd6573e0f608233a5ae8Amit Mahajan        return SubscriptionController.getInstance().getSubIdUsingPhoneId(mPhone.getPhoneId());
1804b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen    }
1805f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal
1806f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal    private void checkCallerIsPhoneOrCarrierApp() {
1807f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal        int uid = Binder.getCallingUid();
1808f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal        int appId = UserHandle.getAppId(uid);
1809f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal        if (appId == Process.PHONE_UID || uid == 0) {
1810f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            return;
1811f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal        }
1812f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal        try {
1813f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            PackageManager pm = mContext.getPackageManager();
1814f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            ApplicationInfo ai = pm.getApplicationInfo(getCarrierAppPackageName(), 0);
1815f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            if (!UserHandle.isSameApp(ai.uid, Binder.getCallingUid())) {
1816f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal                throw new SecurityException("Caller is not phone or carrier app!");
1817f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            }
1818f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal        } catch (PackageManager.NameNotFoundException re) {
1819f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal            throw new SecurityException("Caller is not phone or carrier app!");
1820f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal        }
1821f323afdb70b83e0c851ced2af7594b20412542c3Shishir Agrawal    }
18220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
1823