• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony;
18 
19 import static android.Manifest.permission.SEND_SMS_NO_CONFIRMATION;
20 import static android.telephony.SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE;
21 import static android.telephony.SmsManager.RESULT_ERROR_GENERIC_FAILURE;
22 import static android.telephony.SmsManager.RESULT_ERROR_LIMIT_EXCEEDED;
23 import static android.telephony.SmsManager.RESULT_ERROR_NO_SERVICE;
24 import static android.telephony.SmsManager.RESULT_ERROR_NULL_PDU;
25 import static android.telephony.SmsManager.RESULT_ERROR_RADIO_OFF;
26 import static android.telephony.SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED;
27 import static android.telephony.SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED;
28 
29 import static com.android.internal.telephony.IccSmsInterfaceManager.SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
30 import static com.android.internal.telephony.IccSmsInterfaceManager.SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
31 
32 import android.annotation.Nullable;
33 import android.annotation.UnsupportedAppUsage;
34 import android.annotation.UserIdInt;
35 import android.app.Activity;
36 import android.app.AlertDialog;
37 import android.app.PendingIntent;
38 import android.app.PendingIntent.CanceledException;
39 import android.content.ContentResolver;
40 import android.content.ContentValues;
41 import android.content.Context;
42 import android.content.DialogInterface;
43 import android.content.Intent;
44 import android.content.pm.ApplicationInfo;
45 import android.content.pm.PackageInfo;
46 import android.content.pm.PackageItemInfo;
47 import android.content.pm.PackageManager;
48 import android.content.res.Resources;
49 import android.database.ContentObserver;
50 import android.database.sqlite.SqliteWrapper;
51 import android.net.Uri;
52 import android.os.AsyncResult;
53 import android.os.Binder;
54 import android.os.Handler;
55 import android.os.Message;
56 import android.os.PersistableBundle;
57 import android.os.Process;
58 import android.os.RemoteException;
59 import android.os.UserHandle;
60 import android.provider.Settings;
61 import android.provider.Telephony;
62 import android.provider.Telephony.Sms;
63 import android.service.carrier.CarrierMessagingService;
64 import android.service.carrier.ICarrierMessagingCallback;
65 import android.service.carrier.ICarrierMessagingService;
66 import android.telephony.CarrierConfigManager;
67 import android.telephony.CarrierMessagingServiceManager;
68 import android.telephony.PhoneNumberUtils;
69 import android.telephony.Rlog;
70 import android.telephony.ServiceState;
71 import android.telephony.SmsManager;
72 import android.telephony.TelephonyManager;
73 import android.text.Html;
74 import android.text.Spanned;
75 import android.text.TextUtils;
76 import android.util.EventLog;
77 import android.view.LayoutInflater;
78 import android.view.View;
79 import android.view.ViewGroup;
80 import android.view.WindowManager;
81 import android.widget.Button;
82 import android.widget.CheckBox;
83 import android.widget.CompoundButton;
84 import android.widget.TextView;
85 
86 import com.android.internal.R;
87 import com.android.internal.annotations.VisibleForTesting;
88 import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
89 import com.android.internal.telephony.cdma.sms.UserData;
90 import com.android.internal.telephony.uicc.UiccCard;
91 import com.android.internal.telephony.uicc.UiccController;
92 
93 import java.util.ArrayList;
94 import java.util.HashMap;
95 import java.util.List;
96 import java.util.Random;
97 import java.util.concurrent.atomic.AtomicBoolean;
98 import java.util.concurrent.atomic.AtomicInteger;
99 
100 public abstract class SMSDispatcher extends Handler {
101     static final String TAG = "SMSDispatcher";    // accessed from inner class
102     static final boolean DBG = false;
103     private static final String SEND_NEXT_MSG_EXTRA = "SendNextMsg";
104     protected static final String MAP_KEY_PDU = "pdu";
105     protected static final String MAP_KEY_SMSC = "smsc";
106     protected static final String MAP_KEY_DEST_ADDR = "destAddr";
107     protected static final String MAP_KEY_SC_ADDR = "scAddr";
108     protected static final String MAP_KEY_DEST_PORT = "destPort";
109     protected static final String MAP_KEY_DATA = "data";
110     protected static final String MAP_KEY_TEXT = "text";
111 
112     private static final int PREMIUM_RULE_USE_SIM = 1;
113     private static final int PREMIUM_RULE_USE_NETWORK = 2;
114     private static final int PREMIUM_RULE_USE_BOTH = 3;
115     private final AtomicInteger mPremiumSmsRule = new AtomicInteger(PREMIUM_RULE_USE_SIM);
116     private final SettingsObserver mSettingsObserver;
117 
118     /** SMS send complete. */
119     protected static final int EVENT_SEND_SMS_COMPLETE = 2;
120 
121     /** Retry sending a previously failed SMS message */
122     private static final int EVENT_SEND_RETRY = 3;
123 
124     /** Confirmation required for sending a large number of messages. */
125     private static final int EVENT_SEND_LIMIT_REACHED_CONFIRMATION = 4;
126 
127     /** Send the user confirmed SMS */
128     static final int EVENT_SEND_CONFIRMED_SMS = 5;  // accessed from inner class
129 
130     /** Don't send SMS (user did not confirm). */
131     static final int EVENT_STOP_SENDING = 7;        // accessed from inner class
132 
133     /** Confirmation required for third-party apps sending to an SMS short code. */
134     private static final int EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE = 8;
135 
136     /** Confirmation required for third-party apps sending to an SMS short code. */
137     private static final int EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE = 9;
138 
139     /** Handle status report from {@code CdmaInboundSmsHandler}. */
140     protected static final int EVENT_HANDLE_STATUS_REPORT = 10;
141 
142     // other
143     protected static final int EVENT_NEW_ICC_SMS = 14;
144     protected static final int EVENT_ICC_CHANGED = 15;
145     protected static final int EVENT_GET_IMS_SERVICE = 16;
146 
147 
148     @UnsupportedAppUsage
149     protected Phone mPhone;
150     @UnsupportedAppUsage
151     protected final Context mContext;
152     @UnsupportedAppUsage
153     protected final ContentResolver mResolver;
154     @UnsupportedAppUsage
155     protected final CommandsInterface mCi;
156     @UnsupportedAppUsage
157     protected final TelephonyManager mTelephonyManager;
158 
159     /** Maximum number of times to retry sending a failed SMS. */
160     private static final int MAX_SEND_RETRIES = 3;
161     /** Delay before next send attempt on a failed SMS, in milliseconds. */
162     private static final int SEND_RETRY_DELAY = 2000;
163     /** single part SMS */
164     private static final int SINGLE_PART_SMS = 1;
165     /** Message sending queue limit */
166     private static final int MO_MSG_QUEUE_LIMIT = 5;
167 
168     /**
169      * Message reference for a CONCATENATED_8_BIT_REFERENCE or
170      * CONCATENATED_16_BIT_REFERENCE message set.  Should be
171      * incremented for each set of concatenated messages.
172      * Static field shared by all dispatcher objects.
173      */
174     private static int sConcatenatedRef = new Random().nextInt(256);
175 
176     protected SmsDispatchersController mSmsDispatchersController;
177 
178     /** Number of outgoing SmsTrackers waiting for user confirmation. */
179     private int mPendingTrackerCount;
180 
181     /* Flags indicating whether the current device allows sms service */
182     protected boolean mSmsCapable = true;
183     protected boolean mSmsSendDisabled;
184 
185     @UnsupportedAppUsage
getNextConcatenatedRef()186     protected static int getNextConcatenatedRef() {
187         sConcatenatedRef += 1;
188         return sConcatenatedRef;
189     }
190 
191     /**
192      * Create a new SMS dispatcher.
193      * @param phone the Phone to use
194      */
SMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController)195     protected SMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController) {
196         mPhone = phone;
197         mSmsDispatchersController = smsDispatchersController;
198         mContext = phone.getContext();
199         mResolver = mContext.getContentResolver();
200         mCi = phone.mCi;
201         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
202         mSettingsObserver = new SettingsObserver(this, mPremiumSmsRule, mContext);
203         mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
204                 Settings.Global.SMS_SHORT_CODE_RULE), false, mSettingsObserver);
205 
206         mSmsCapable = mContext.getResources().getBoolean(
207                 com.android.internal.R.bool.config_sms_capable);
208         mSmsSendDisabled = !mTelephonyManager.getSmsSendCapableForPhone(
209                 mPhone.getPhoneId(), mSmsCapable);
210         Rlog.d(TAG, "SMSDispatcher: ctor mSmsCapable=" + mSmsCapable + " format=" + getFormat()
211                 + " mSmsSendDisabled=" + mSmsSendDisabled);
212     }
213 
214     /**
215      * Observe the secure setting for updated premium sms determination rules
216      */
217     private static class SettingsObserver extends ContentObserver {
218         private final AtomicInteger mPremiumSmsRule;
219         private final Context mContext;
SettingsObserver(Handler handler, AtomicInteger premiumSmsRule, Context context)220         SettingsObserver(Handler handler, AtomicInteger premiumSmsRule, Context context) {
221             super(handler);
222             mPremiumSmsRule = premiumSmsRule;
223             mContext = context;
224             onChange(false); // load initial value;
225         }
226 
227         @Override
onChange(boolean selfChange)228         public void onChange(boolean selfChange) {
229             mPremiumSmsRule.set(Settings.Global.getInt(mContext.getContentResolver(),
230                     Settings.Global.SMS_SHORT_CODE_RULE, PREMIUM_RULE_USE_SIM));
231         }
232     }
233 
234     /** Unregister for incoming SMS events. */
235     @UnsupportedAppUsage
dispose()236     public void dispose() {
237         mContext.getContentResolver().unregisterContentObserver(mSettingsObserver);
238     }
239 
240     /**
241      * The format of the message PDU in the associated broadcast intent.
242      * This will be either "3gpp" for GSM/UMTS/LTE messages in 3GPP format
243      * or "3gpp2" for CDMA/LTE messages in 3GPP2 format.
244      *
245      * Note: All applications which handle incoming SMS messages by processing the
246      * SMS_RECEIVED_ACTION broadcast intent MUST pass the "format" extra from the intent
247      * into the new methods in {@link android.telephony.SmsMessage} which take an
248      * extra format parameter. This is required in order to correctly decode the PDU on
249      * devices which require support for both 3GPP and 3GPP2 formats at the same time,
250      * such as CDMA/LTE devices and GSM/CDMA world phones.
251      *
252      * @return the format of the message PDU
253      */
getFormat()254     protected abstract String getFormat();
255 
256     /**
257      * Pass the Message object to subclass to handle. Currently used to pass CDMA status reports
258      * from {@link com.android.internal.telephony.cdma.CdmaInboundSmsHandler}.
259      * @param o the SmsMessage containing the status report
260      */
handleStatusReport(Object o)261     protected void handleStatusReport(Object o) {
262         Rlog.d(TAG, "handleStatusReport() called with no subclass.");
263     }
264 
265     /* TODO: Need to figure out how to keep track of status report routing in a
266      *       persistent manner. If the phone process restarts (reboot or crash),
267      *       we will lose this list and any status reports that come in after
268      *       will be dropped.
269      */
270     /** Sent messages awaiting a delivery status report. */
271     @UnsupportedAppUsage
272     protected final ArrayList<SmsTracker> deliveryPendingList = new ArrayList<SmsTracker>();
273 
274     /**
275      * Handles events coming from the phone stack. Overridden from handler.
276      *
277      * @param msg the message to handle
278      */
279     @Override
handleMessage(Message msg)280     public void handleMessage(Message msg) {
281         switch (msg.what) {
282         case EVENT_SEND_SMS_COMPLETE:
283             // An outbound SMS has been successfully transferred, or failed.
284             handleSendComplete((AsyncResult) msg.obj);
285             break;
286 
287         case EVENT_SEND_RETRY:
288             Rlog.d(TAG, "SMS retry..");
289             sendRetrySms((SmsTracker) msg.obj);
290             break;
291 
292         case EVENT_SEND_LIMIT_REACHED_CONFIRMATION:
293             handleReachSentLimit((SmsTracker)(msg.obj));
294             break;
295 
296         case EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE:
297             handleConfirmShortCode(false, (SmsTracker)(msg.obj));
298             break;
299 
300         case EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE:
301             handleConfirmShortCode(true, (SmsTracker)(msg.obj));
302             break;
303 
304         case EVENT_SEND_CONFIRMED_SMS:
305         {
306             SmsTracker tracker = (SmsTracker) msg.obj;
307             if (tracker.isMultipart()) {
308                 sendMultipartSms(tracker);
309             } else {
310                 if (mPendingTrackerCount > 1) {
311                     tracker.mExpectMore = true;
312                 } else {
313                     tracker.mExpectMore = false;
314                 }
315                 sendSms(tracker);
316             }
317             mPendingTrackerCount--;
318             break;
319         }
320 
321         case EVENT_STOP_SENDING:
322         {
323             SmsTracker tracker = (SmsTracker) msg.obj;
324             if (msg.arg1 == ConfirmDialogListener.SHORT_CODE_MSG) {
325                 if (msg.arg2 == ConfirmDialogListener.NEVER_ALLOW) {
326                     tracker.onFailed(mContext,
327                             RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED, 0/*errorCode*/);
328                     Rlog.d(TAG, "SMSDispatcher: EVENT_STOP_SENDING - "
329                             + "sending SHORT_CODE_NEVER_ALLOWED error code.");
330                 } else {
331                     tracker.onFailed(mContext,
332                             RESULT_ERROR_SHORT_CODE_NOT_ALLOWED, 0/*errorCode*/);
333                     Rlog.d(TAG, "SMSDispatcher: EVENT_STOP_SENDING - "
334                             + "sending SHORT_CODE_NOT_ALLOWED error code.");
335                 }
336             } else if (msg.arg1 == ConfirmDialogListener.RATE_LIMIT) {
337                 tracker.onFailed(mContext, RESULT_ERROR_LIMIT_EXCEEDED, 0/*errorCode*/);
338                 Rlog.d(TAG, "SMSDispatcher: EVENT_STOP_SENDING - "
339                         + "sending LIMIT_EXCEEDED error code.");
340             } else {
341                 Rlog.e(TAG, "SMSDispatcher: EVENT_STOP_SENDING - unexpected cases.");
342             }
343             mPendingTrackerCount--;
344             break;
345         }
346 
347         case EVENT_HANDLE_STATUS_REPORT:
348             handleStatusReport(msg.obj);
349             break;
350 
351         default:
352             Rlog.e(TAG, "handleMessage() ignoring message of unexpected type " + msg.what);
353         }
354     }
355 
356     /**
357      * Use the carrier messaging service to send a data or text SMS.
358      */
359     protected abstract class SmsSender extends CarrierMessagingServiceManager {
360         protected final SmsTracker mTracker;
361         // Initialized in sendSmsByCarrierApp
362         protected volatile SmsSenderCallback mSenderCallback;
363 
SmsSender(SmsTracker tracker)364         protected SmsSender(SmsTracker tracker) {
365             mTracker = tracker;
366         }
367 
sendSmsByCarrierApp(String carrierPackageName, SmsSenderCallback senderCallback)368         public void sendSmsByCarrierApp(String carrierPackageName,
369                                         SmsSenderCallback senderCallback) {
370             mSenderCallback = senderCallback;
371             if (!bindToCarrierMessagingService(mContext, carrierPackageName)) {
372                 Rlog.e(TAG, "bindService() for carrier messaging service failed");
373                 mSenderCallback.onSendSmsComplete(
374                         CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
375                         0 /* messageRef */);
376             } else {
377                 Rlog.d(TAG, "bindService() for carrier messaging service succeeded");
378             }
379         }
380     }
381 
getSendSmsFlag(@ullable PendingIntent deliveryIntent)382     private static int getSendSmsFlag(@Nullable PendingIntent deliveryIntent) {
383         if (deliveryIntent == null) {
384             return 0;
385         }
386         return CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS;
387     }
388 
389     /**
390      * Use the carrier messaging service to send a text SMS.
391      */
392     protected final class TextSmsSender extends SmsSender {
TextSmsSender(SmsTracker tracker)393         public TextSmsSender(SmsTracker tracker) {
394             super(tracker);
395         }
396 
397         @Override
onServiceReady(ICarrierMessagingService carrierMessagingService)398         protected void onServiceReady(ICarrierMessagingService carrierMessagingService) {
399             HashMap<String, Object> map = mTracker.getData();
400             String text = (String) map.get(MAP_KEY_TEXT);
401 
402             if (text != null) {
403                 try {
404                     carrierMessagingService.sendTextSms(text, getSubId(),
405                             mTracker.mDestAddress, getSendSmsFlag(mTracker.mDeliveryIntent),
406                             mSenderCallback);
407                 } catch (RemoteException e) {
408                     Rlog.e(TAG, "Exception sending the SMS: " + e);
409                     mSenderCallback.onSendSmsComplete(
410                             CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
411                             0 /* messageRef */);
412                 }
413             } else {
414                 mSenderCallback.onSendSmsComplete(
415                         CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
416                         0 /* messageRef */);
417             }
418         }
419     }
420 
421     /**
422      * Use the carrier messaging service to send a data SMS.
423      */
424     protected final class DataSmsSender extends SmsSender {
DataSmsSender(SmsTracker tracker)425         public DataSmsSender(SmsTracker tracker) {
426             super(tracker);
427         }
428 
429         @Override
onServiceReady(ICarrierMessagingService carrierMessagingService)430         protected void onServiceReady(ICarrierMessagingService carrierMessagingService) {
431             HashMap<String, Object> map = mTracker.getData();
432             byte[] data = (byte[]) map.get(MAP_KEY_DATA);
433             int destPort = (int) map.get(MAP_KEY_DEST_PORT);
434 
435             if (data != null) {
436                 try {
437                     carrierMessagingService.sendDataSms(data, getSubId(),
438                             mTracker.mDestAddress, destPort,
439                             getSendSmsFlag(mTracker.mDeliveryIntent), mSenderCallback);
440                 } catch (RemoteException e) {
441                     Rlog.e(TAG, "Exception sending the SMS: " + e);
442                     mSenderCallback.onSendSmsComplete(
443                             CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
444                             0 /* messageRef */);
445                 }
446             } else {
447                 mSenderCallback.onSendSmsComplete(
448                         CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
449                         0 /* messageRef */);
450             }
451         }
452     }
453 
454     /**
455      * Callback for TextSmsSender and DataSmsSender from the carrier messaging service.
456      * Once the result is ready, the carrier messaging service connection is disposed.
457      */
458     protected final class SmsSenderCallback extends ICarrierMessagingCallback.Stub {
459         private final SmsSender mSmsSender;
460 
SmsSenderCallback(SmsSender smsSender)461         public SmsSenderCallback(SmsSender smsSender) {
462             mSmsSender = smsSender;
463         }
464 
465         /**
466          * This method should be called only once.
467          */
468         @Override
onSendSmsComplete(int result, int messageRef)469         public void onSendSmsComplete(int result, int messageRef) {
470             checkCallerIsPhoneOrCarrierApp();
471             final long identity = Binder.clearCallingIdentity();
472             try {
473                 mSmsSender.disposeConnection(mContext);
474                 processSendSmsResponse(mSmsSender.mTracker, result, messageRef);
475             } finally {
476                 Binder.restoreCallingIdentity(identity);
477             }
478         }
479 
480         @Override
onSendMultipartSmsComplete(int result, int[] messageRefs)481         public void onSendMultipartSmsComplete(int result, int[] messageRefs) {
482             Rlog.e(TAG, "Unexpected onSendMultipartSmsComplete call with result: " + result);
483         }
484 
485         @Override
onFilterComplete(int result)486         public void onFilterComplete(int result) {
487             Rlog.e(TAG, "Unexpected onFilterComplete call with result: " + result);
488         }
489 
490         @Override
onSendMmsComplete(int result, byte[] sendConfPdu)491         public void onSendMmsComplete(int result, byte[] sendConfPdu) {
492             Rlog.e(TAG, "Unexpected onSendMmsComplete call with result: " + result);
493         }
494 
495         @Override
onDownloadMmsComplete(int result)496         public void onDownloadMmsComplete(int result) {
497             Rlog.e(TAG, "Unexpected onDownloadMmsComplete call with result: " + result);
498         }
499     }
500 
501     @UnsupportedAppUsage
processSendSmsResponse(SmsTracker tracker, int result, int messageRef)502     private void processSendSmsResponse(SmsTracker tracker, int result, int messageRef) {
503         if (tracker == null) {
504             Rlog.e(TAG, "processSendSmsResponse: null tracker");
505             return;
506         }
507 
508         SmsResponse smsResponse = new SmsResponse(
509                 messageRef, null /* ackPdu */, -1 /* unknown error code */);
510 
511         switch (result) {
512         case CarrierMessagingService.SEND_STATUS_OK:
513             Rlog.d(TAG, "Sending SMS by IP succeeded.");
514             sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE,
515                                       new AsyncResult(tracker,
516                                                       smsResponse,
517                                                       null /* exception*/ )));
518             break;
519         case CarrierMessagingService.SEND_STATUS_ERROR:
520             Rlog.d(TAG, "Sending SMS by IP failed.");
521             sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE,
522                     new AsyncResult(tracker, smsResponse,
523                             new CommandException(CommandException.Error.GENERIC_FAILURE))));
524             break;
525         case CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK:
526             Rlog.d(TAG, "Sending SMS by IP failed. Retry on carrier network.");
527             sendSubmitPdu(tracker);
528             break;
529         default:
530             Rlog.d(TAG, "Unknown result " + result + " Retry on carrier network.");
531             sendSubmitPdu(tracker);
532         }
533     }
534 
535     /**
536      * Use the carrier messaging service to send a multipart text SMS.
537      */
538     private final class MultipartSmsSender extends CarrierMessagingServiceManager {
539         private final List<String> mParts;
540         public final SmsTracker[] mTrackers;
541         // Initialized in sendSmsByCarrierApp
542         private volatile MultipartSmsSenderCallback mSenderCallback;
543 
MultipartSmsSender(ArrayList<String> parts, SmsTracker[] trackers)544         MultipartSmsSender(ArrayList<String> parts, SmsTracker[] trackers) {
545             mParts = parts;
546             mTrackers = trackers;
547         }
548 
549         @UnsupportedAppUsage
sendSmsByCarrierApp(String carrierPackageName, MultipartSmsSenderCallback senderCallback)550         void sendSmsByCarrierApp(String carrierPackageName,
551                                  MultipartSmsSenderCallback senderCallback) {
552             mSenderCallback = senderCallback;
553             if (!bindToCarrierMessagingService(mContext, carrierPackageName)) {
554                 Rlog.e(TAG, "bindService() for carrier messaging service failed");
555                 mSenderCallback.onSendMultipartSmsComplete(
556                         CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
557                         null /* smsResponse */);
558             } else {
559                 Rlog.d(TAG, "bindService() for carrier messaging service succeeded");
560             }
561         }
562 
563         @Override
onServiceReady(ICarrierMessagingService carrierMessagingService)564         protected void onServiceReady(ICarrierMessagingService carrierMessagingService) {
565             try {
566                 carrierMessagingService.sendMultipartTextSms(
567                         mParts, getSubId(), mTrackers[0].mDestAddress,
568                         getSendSmsFlag(mTrackers[0].mDeliveryIntent), mSenderCallback);
569             } catch (RemoteException e) {
570                 Rlog.e(TAG, "Exception sending the SMS: " + e);
571                 mSenderCallback.onSendMultipartSmsComplete(
572                         CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK,
573                         null /* smsResponse */);
574             }
575         }
576     }
577 
578     /**
579      * Callback for MultipartSmsSender from the carrier messaging service.
580      * Once the result is ready, the carrier messaging service connection is disposed.
581      */
582     private final class MultipartSmsSenderCallback extends ICarrierMessagingCallback.Stub {
583         private final MultipartSmsSender mSmsSender;
584 
MultipartSmsSenderCallback(MultipartSmsSender smsSender)585         MultipartSmsSenderCallback(MultipartSmsSender smsSender) {
586             mSmsSender = smsSender;
587         }
588 
589         @Override
onSendSmsComplete(int result, int messageRef)590         public void onSendSmsComplete(int result, int messageRef) {
591             Rlog.e(TAG, "Unexpected onSendSmsComplete call with result: " + result);
592         }
593 
594         /**
595          * This method should be called only once.
596          */
597         @Override
onSendMultipartSmsComplete(int result, int[] messageRefs)598         public void onSendMultipartSmsComplete(int result, int[] messageRefs) {
599             mSmsSender.disposeConnection(mContext);
600 
601             if (mSmsSender.mTrackers == null) {
602                 Rlog.e(TAG, "Unexpected onSendMultipartSmsComplete call with null trackers.");
603                 return;
604             }
605 
606             checkCallerIsPhoneOrCarrierApp();
607             final long identity = Binder.clearCallingIdentity();
608             try {
609                 for (int i = 0; i < mSmsSender.mTrackers.length; i++) {
610                     int messageRef = 0;
611                     if (messageRefs != null && messageRefs.length > i) {
612                         messageRef = messageRefs[i];
613                     }
614                     processSendSmsResponse(mSmsSender.mTrackers[i], result, messageRef);
615                 }
616             } finally {
617                 Binder.restoreCallingIdentity(identity);
618             }
619         }
620 
621         @Override
onFilterComplete(int result)622         public void onFilterComplete(int result) {
623             Rlog.e(TAG, "Unexpected onFilterComplete call with result: " + result);
624         }
625 
626         @Override
onSendMmsComplete(int result, byte[] sendConfPdu)627         public void onSendMmsComplete(int result, byte[] sendConfPdu) {
628             Rlog.e(TAG, "Unexpected onSendMmsComplete call with result: " + result);
629         }
630 
631         @Override
onDownloadMmsComplete(int result)632         public void onDownloadMmsComplete(int result) {
633             Rlog.e(TAG, "Unexpected onDownloadMmsComplete call with result: " + result);
634         }
635     }
636 
637     /**
638      * Send an SMS PDU. Usually just calls {@link sendRawPdu}.
639      */
640     @UnsupportedAppUsage
sendSubmitPdu(SmsTracker tracker)641     private void sendSubmitPdu(SmsTracker tracker) {
642         if (shouldBlockSmsForEcbm()) {
643             Rlog.d(TAG, "Block SMS in Emergency Callback mode");
644             tracker.onFailed(mContext, SmsManager.RESULT_ERROR_NO_SERVICE, 0/*errorCode*/);
645         } else {
646             sendRawPdu(tracker);
647         }
648     }
649 
650     /**
651      * @return true if MO SMS should be blocked for Emergency Callback Mode.
652      */
shouldBlockSmsForEcbm()653     protected abstract boolean shouldBlockSmsForEcbm();
654 
655     /**
656      * Called when SMS send completes. Broadcasts a sentIntent on success.
657      * On failure, either sets up retries or broadcasts a sentIntent with
658      * the failure in the result code.
659      *
660      * @param ar AsyncResult passed into the message handler.  ar.result should
661      *           an SmsResponse instance if send was successful.  ar.userObj
662      *           should be an SmsTracker instance.
663      */
handleSendComplete(AsyncResult ar)664     protected void handleSendComplete(AsyncResult ar) {
665         SmsTracker tracker = (SmsTracker) ar.userObj;
666         PendingIntent sentIntent = tracker.mSentIntent;
667 
668         if (ar.result != null) {
669             tracker.mMessageRef = ((SmsResponse)ar.result).mMessageRef;
670         } else {
671             Rlog.d(TAG, "SmsResponse was null");
672         }
673 
674         if (ar.exception == null) {
675             if (DBG) Rlog.d(TAG, "SMS send complete. Broadcasting intent: " + sentIntent);
676 
677             if (tracker.mDeliveryIntent != null) {
678                 // Expecting a status report.  Add it to the list.
679                 deliveryPendingList.add(tracker);
680             }
681             tracker.onSent(mContext);
682             mPhone.notifySmsSent(tracker.mDestAddress);
683         } else {
684             if (DBG) Rlog.d(TAG, "SMS send failed");
685 
686             int ss = mPhone.getServiceState().getState();
687 
688             if ( tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) {
689                 // This is retry after failure over IMS but voice is not available.
690                 // Set retry to max allowed, so no retry is sent and
691                 //   cause RESULT_ERROR_GENERIC_FAILURE to be returned to app.
692                 tracker.mRetryCount = MAX_SEND_RETRIES;
693 
694                 Rlog.d(TAG, "handleSendComplete: Skipping retry: "
695                 +" isIms()="+isIms()
696                 +" mRetryCount="+tracker.mRetryCount
697                 +" mImsRetry="+tracker.mImsRetry
698                 +" mMessageRef="+tracker.mMessageRef
699                 +" SS= "+mPhone.getServiceState().getState());
700             }
701 
702             // if sms over IMS is not supported on data and voice is not available...
703             if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
704                 tracker.onFailed(mContext, getNotInServiceError(ss), 0/*errorCode*/);
705             } else if ((((CommandException)(ar.exception)).getCommandError()
706                     == CommandException.Error.SMS_FAIL_RETRY) &&
707                    tracker.mRetryCount < MAX_SEND_RETRIES) {
708                 // Retry after a delay if needed.
709                 // TODO: According to TS 23.040, 9.2.3.6, we should resend
710                 //       with the same TP-MR as the failed message, and
711                 //       TP-RD set to 1.  However, we don't have a means of
712                 //       knowing the MR for the failed message (EF_SMSstatus
713                 //       may or may not have the MR corresponding to this
714                 //       message, depending on the failure).  Also, in some
715                 //       implementations this retry is handled by the baseband.
716                 tracker.mRetryCount++;
717                 Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker);
718                 sendMessageDelayed(retryMsg, SEND_RETRY_DELAY);
719             } else {
720                 int errorCode = 0;
721                 if (ar.result != null) {
722                     errorCode = ((SmsResponse)ar.result).mErrorCode;
723                 }
724                 int error = RESULT_ERROR_GENERIC_FAILURE;
725                 if (((CommandException)(ar.exception)).getCommandError()
726                         == CommandException.Error.FDN_CHECK_FAILURE) {
727                     error = RESULT_ERROR_FDN_CHECK_FAILURE;
728                 }
729                 tracker.onFailed(mContext, error, errorCode);
730             }
731         }
732     }
733 
734     /**
735      * Handles outbound message when the phone is not in service.
736      *
737      * @param ss     Current service state.  Valid values are:
738      *                  OUT_OF_SERVICE
739      *                  EMERGENCY_ONLY
740      *                  POWER_OFF
741      * @param sentIntent the PendingIntent to send the error to
742      */
handleNotInService(int ss, PendingIntent sentIntent)743     protected static void handleNotInService(int ss, PendingIntent sentIntent) {
744         if (sentIntent != null) {
745             try {
746                 if (ss == ServiceState.STATE_POWER_OFF) {
747                     sentIntent.send(RESULT_ERROR_RADIO_OFF);
748                 } else {
749                     sentIntent.send(RESULT_ERROR_NO_SERVICE);
750                 }
751             } catch (CanceledException ex) {
752                 Rlog.e(TAG, "Failed to send result");
753             }
754         }
755     }
756 
757     /**
758      * @param ss service state
759      * @return The result error based on input service state for not in service error
760      */
getNotInServiceError(int ss)761     protected static int getNotInServiceError(int ss) {
762         if (ss == ServiceState.STATE_POWER_OFF) {
763             return RESULT_ERROR_RADIO_OFF;
764         }
765         return RESULT_ERROR_NO_SERVICE;
766     }
767 
768     /**
769      * Send a data based SMS to a specific application port.
770      *
771      * @param callingPackage the package name of the calling app
772      * @param destAddr the address to send the message to
773      * @param scAddr is the service center address or null to use
774      *  the current default SMSC
775      * @param destPort the port to deliver the message to
776      * @param data the body of the message to send
777      * @param sentIntent if not NULL this <code>PendingIntent</code> is
778      *  broadcast when the message is successfully sent, or failed.
779      *  The result code will be <code>Activity.RESULT_OK<code> for success,
780      *  or one of these errors:<br>
781      *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
782      *  <code>RESULT_ERROR_RADIO_OFF</code><br>
783      *  <code>RESULT_ERROR_NULL_PDU</code><br>
784      *  <code>RESULT_ERROR_NO_SERVICE</code><br>.
785      *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
786      *  the extra "errorCode" containing a radio technology specific value,
787      *  generally only useful for troubleshooting.<br>
788      *  The per-application based SMS control checks sentIntent. If sentIntent
789      *  is NULL the caller will be checked against all unknown applications,
790      *  which cause smaller number of SMS to be sent in checking period.
791      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
792      *  broadcast when the message is delivered to the recipient.  The
793      *  raw pdu of the status report is in the extended data ("pdu").
794      */
795     @UnsupportedAppUsage
sendData(String callingPackage, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm)796     protected void sendData(String callingPackage, String destAddr, String scAddr, int destPort,
797             byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm) {
798         SmsMessageBase.SubmitPduBase pdu = getSubmitPdu(
799                 scAddr, destAddr, destPort, data, (deliveryIntent != null));
800         if (pdu != null) {
801             HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);
802             SmsTracker tracker = getSmsTracker(callingPackage, map, sentIntent, deliveryIntent,
803                     getFormat(), null /*messageUri*/, false /*expectMore*/,
804                     null /*fullMessageText*/, false /*isText*/,
805                     true /*persistMessage*/, isForVvm);
806 
807             if (!sendSmsByCarrierApp(true /* isDataSms */, tracker)) {
808                 sendSubmitPdu(tracker);
809             }
810         } else {
811             Rlog.e(TAG, "SMSDispatcher.sendData(): getSubmitPdu() returned null");
812             triggerSentIntentForFailure(sentIntent);
813         }
814     }
815 
816     /**
817      * Send a text based SMS.
818      *  @param destAddr the address to send the message to
819      * @param scAddr is the service center address or null to use
820      *  the current default SMSC
821      * @param text the body of the message to send
822      * @param sentIntent if not NULL this <code>PendingIntent</code> is
823      *  broadcast when the message is successfully sent, or failed.
824      *  The result code will be <code>Activity.RESULT_OK<code> for success,
825      *  or one of these errors:<br>
826      *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
827      *  <code>RESULT_ERROR_RADIO_OFF</code><br>
828      *  <code>RESULT_ERROR_NULL_PDU</code><br>
829      *  <code>RESULT_ERROR_NO_SERVICE</code><br>.
830      *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
831      *  the extra "errorCode" containing a radio technology specific value,
832      *  generally only useful for troubleshooting.<br>
833      *  The per-application based SMS control checks sentIntent. If sentIntent
834      *  is NULL the caller will be checked against all unknown applications,
835      *  which cause smaller number of SMS to be sent in checking period.
836      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
837      *  broadcast when the message is delivered to the recipient.  The
838      * @param messageUri optional URI of the message if it is already stored in the system
839      * @param callingPkg the calling package name
840      * @param persistMessage whether to save the sent message into SMS DB for a
841      *   non-default SMS app.
842      *
843      * @param priority Priority level of the message
844      *  Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
845      *  ---------------------------------
846      *  PRIORITY      | Level of Priority
847      *  ---------------------------------
848      *      '00'      |     Normal
849      *      '01'      |     Interactive
850      *      '10'      |     Urgent
851      *      '11'      |     Emergency
852      *  ----------------------------------
853      *  Any Other values included Negative considered as Invalid Priority Indicator of the message.
854      * @param expectMore is a boolean to indicate the sending messages through same link or not.
855      * @param validityPeriod Validity Period of the message in mins.
856      *  Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
857      *  Validity Period(Minimum) -> 5 mins
858      *  Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
859      *  Any Other values included Negative considered as Invalid Validity Period of the message.
860      */
sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri, String callingPkg, boolean persistMessage, int priority, boolean expectMore, int validityPeriod, boolean isForVvm)861     public void sendText(String destAddr, String scAddr, String text,
862                          PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri,
863                          String callingPkg, boolean persistMessage, int priority,
864                          boolean expectMore, int validityPeriod, boolean isForVvm) {
865         Rlog.d(TAG, "sendText");
866         SmsMessageBase.SubmitPduBase pdu = getSubmitPdu(
867                 scAddr, destAddr, text, (deliveryIntent != null), null, priority, validityPeriod);
868         if (pdu != null) {
869             HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
870             SmsTracker tracker = getSmsTracker(callingPkg, map, sentIntent, deliveryIntent,
871                     getFormat(), messageUri, expectMore, text, true /*isText*/,
872                     persistMessage, priority, validityPeriod, isForVvm);
873 
874             if (!sendSmsByCarrierApp(false /* isDataSms */, tracker)) {
875                 sendSubmitPdu(tracker);
876             }
877         } else {
878             Rlog.e(TAG, "SmsDispatcher.sendText(): getSubmitPdu() returned null");
879             triggerSentIntentForFailure(sentIntent);
880         }
881     }
882 
triggerSentIntentForFailure(PendingIntent sentIntent)883     private void triggerSentIntentForFailure(PendingIntent sentIntent) {
884         if (sentIntent != null) {
885             try {
886                 sentIntent.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE);
887             } catch (CanceledException ex) {
888                 Rlog.e(TAG, "Intent has been canceled!");
889             }
890         }
891     }
892 
triggerSentIntentForFailure(List<PendingIntent> sentIntents)893     private void triggerSentIntentForFailure(List<PendingIntent> sentIntents) {
894         if (sentIntents == null) {
895             return;
896         }
897 
898         for (PendingIntent sentIntent : sentIntents) {
899             triggerSentIntentForFailure(sentIntent);
900         }
901     }
902 
sendSmsByCarrierApp(boolean isDataSms, SmsTracker tracker )903     private boolean sendSmsByCarrierApp(boolean isDataSms, SmsTracker tracker ) {
904         String carrierPackage = getCarrierAppPackageName();
905         if (carrierPackage != null) {
906             Rlog.d(TAG, "Found carrier package.");
907             SmsSender smsSender;
908             if (isDataSms) {
909                 smsSender = new DataSmsSender(tracker);
910             } else {
911                 smsSender = new TextSmsSender(tracker);
912             }
913             smsSender.sendSmsByCarrierApp(carrierPackage, new SmsSenderCallback(smsSender));
914             return true;
915         }
916 
917         return false;
918     }
919 
getSubmitPdu(String scAddr, String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader, int priority, int validityPeriod)920     protected abstract SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
921             String message, boolean statusReportRequested, SmsHeader smsHeader,
922             int priority, int validityPeriod);
923 
getSubmitPdu(String scAddr, String destAddr, int destPort, byte[] message, boolean statusReportRequested)924     protected abstract SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
925             int destPort, byte[] message, boolean statusReportRequested);
926 
927     /**
928      * Calculate the number of septets needed to encode the message. This function should only be
929      * called for individual segments of multipart message.
930      *
931      * @param messageBody the message to encode
932      * @param use7bitOnly ignore (but still count) illegal characters if true
933      * @return TextEncodingDetails
934      */
935     @UnsupportedAppUsage
calculateLength(CharSequence messageBody, boolean use7bitOnly)936     protected abstract TextEncodingDetails calculateLength(CharSequence messageBody,
937             boolean use7bitOnly);
938 
939     /**
940      * Send a multi-part text based SMS.
941      *  @param destAddr the address to send the message to
942      * @param scAddr is the service center address or null to use
943      *   the current default SMSC
944      * @param parts an <code>ArrayList</code> of strings that, in order,
945      *   comprise the original message
946      * @param sentIntents if not null, an <code>ArrayList</code> of
947      *   <code>PendingIntent</code>s (one for each message part) that is
948      *   broadcast when the corresponding message part has been sent.
949      *   The result code will be <code>Activity.RESULT_OK<code> for success,
950      *   or one of these errors:
951      *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
952      *   <code>RESULT_ERROR_RADIO_OFF</code>
953      *   <code>RESULT_ERROR_NULL_PDU</code>
954      *   <code>RESULT_ERROR_NO_SERVICE</code>.
955      *  The per-application based SMS control checks sentIntent. If sentIntent
956      *  is NULL the caller will be checked against all unknown applications,
957      *  which cause smaller number of SMS to be sent in checking period.
958      * @param deliveryIntents if not null, an <code>ArrayList</code> of
959      *   <code>PendingIntent</code>s (one for each message part) that is
960      *   broadcast when the corresponding message part has been delivered
961      *   to the recipient.  The raw pdu of the status report is in the
962      * @param messageUri optional URI of the message if it is already stored in the system
963      * @param callingPkg the calling package name
964      * @param persistMessage whether to save the sent message into SMS DB for a
965      *   non-default SMS app.
966      * @param priority Priority level of the message
967      *  Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
968      *  ---------------------------------
969      *  PRIORITY      | Level of Priority
970      *  ---------------------------------
971      *      '00'      |     Normal
972      *      '01'      |     Interactive
973      *      '10'      |     Urgent
974      *      '11'      |     Emergency
975      *  ----------------------------------
976      *  Any Other values included Negative considered as Invalid Priority Indicator of the message.
977      * @param expectMore is a boolean to indicate the sending messages through same link or not.
978      * @param validityPeriod Validity Period of the message in mins.
979      *  Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
980      *  Validity Period(Minimum) -> 5 mins
981      *  Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
982      *  Any Other values included Negative considered as Invalid Validity Period of the message.
983      */
984     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
sendMultipartText(String destAddr, String scAddr, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg, boolean persistMessage, int priority, boolean expectMore, int validityPeriod)985     public void sendMultipartText(String destAddr, String scAddr,
986             ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
987             ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg,
988             boolean persistMessage, int priority, boolean expectMore, int validityPeriod) {
989         final String fullMessageText = getMultipartMessageText(parts);
990         int refNumber = getNextConcatenatedRef() & 0x00FF;
991         int encoding = SmsConstants.ENCODING_UNKNOWN;
992         int msgCount = parts.size();
993         if (msgCount < 1) {
994             triggerSentIntentForFailure(sentIntents);
995             return;
996         }
997 
998         TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount];
999         for (int i = 0; i < msgCount; i++) {
1000             TextEncodingDetails details = calculateLength(parts.get(i), false);
1001             if (encoding != details.codeUnitSize
1002                     && (encoding == SmsConstants.ENCODING_UNKNOWN
1003                             || encoding == SmsConstants.ENCODING_7BIT)) {
1004                 encoding = details.codeUnitSize;
1005             }
1006             encodingForParts[i] = details;
1007         }
1008 
1009         SmsTracker[] trackers = new SmsTracker[msgCount];
1010 
1011         // States to track at the message level (for all parts)
1012         final AtomicInteger unsentPartCount = new AtomicInteger(msgCount);
1013         final AtomicBoolean anyPartFailed = new AtomicBoolean(false);
1014 
1015         for (int i = 0; i < msgCount; i++) {
1016             SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
1017             concatRef.refNumber = refNumber;
1018             concatRef.seqNumber = i + 1;  // 1-based sequence
1019             concatRef.msgCount = msgCount;
1020             // TODO: We currently set this to true since our messaging app will never
1021             // send more than 255 parts (it converts the message to MMS well before that).
1022             // However, we should support 3rd party messaging apps that might need 16-bit
1023             // references
1024             // Note:  It's not sufficient to just flip this bit to true; it will have
1025             // ripple effects (several calculations assume 8-bit ref).
1026             concatRef.isEightBits = true;
1027             SmsHeader smsHeader = new SmsHeader();
1028             smsHeader.concatRef = concatRef;
1029 
1030             // Set the national language tables for 3GPP 7-bit encoding, if enabled.
1031             if (encoding == SmsConstants.ENCODING_7BIT) {
1032                 smsHeader.languageTable = encodingForParts[i].languageTable;
1033                 smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable;
1034             }
1035 
1036             PendingIntent sentIntent = null;
1037             if (sentIntents != null && sentIntents.size() > i) {
1038                 sentIntent = sentIntents.get(i);
1039             }
1040 
1041             PendingIntent deliveryIntent = null;
1042             if (deliveryIntents != null && deliveryIntents.size() > i) {
1043                 deliveryIntent = deliveryIntents.get(i);
1044             }
1045 
1046             trackers[i] =
1047                 getNewSubmitPduTracker(callingPkg, destAddr, scAddr, parts.get(i), smsHeader,
1048                         encoding, sentIntent, deliveryIntent, (i == (msgCount - 1)),
1049                         unsentPartCount, anyPartFailed, messageUri,
1050                         fullMessageText, priority, expectMore, validityPeriod);
1051             if (trackers[i] == null) {
1052                 triggerSentIntentForFailure(sentIntents);
1053                 return;
1054             }
1055             trackers[i].mPersistMessage = persistMessage;
1056         }
1057 
1058         String carrierPackage = getCarrierAppPackageName();
1059         if (carrierPackage != null) {
1060             Rlog.d(TAG, "Found carrier package.");
1061             MultipartSmsSender smsSender = new MultipartSmsSender(parts, trackers);
1062             smsSender.sendSmsByCarrierApp(carrierPackage,
1063                     new MultipartSmsSenderCallback(smsSender));
1064         } else {
1065             Rlog.v(TAG, "No carrier package.");
1066             for (SmsTracker tracker : trackers) {
1067                 sendSubmitPdu(tracker);
1068             }
1069         }
1070     }
1071 
1072     /**
1073      * Create a new SubmitPdu and return the SMS tracker.
1074      */
getNewSubmitPduTracker(String callingPackage, String destinationAddress, String scAddress, String message, SmsHeader smsHeader, int encoding, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart, AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, String fullMessageText, int priority, boolean expectMore, int validityPeriod)1075     private SmsTracker getNewSubmitPduTracker(String callingPackage, String destinationAddress,
1076             String scAddress, String message, SmsHeader smsHeader, int encoding,
1077             PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart,
1078             AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
1079             String fullMessageText, int priority, boolean expectMore, int validityPeriod) {
1080         if (isCdmaMo()) {
1081             UserData uData = new UserData();
1082             uData.payloadStr = message;
1083             uData.userDataHeader = smsHeader;
1084             if (encoding == SmsConstants.ENCODING_7BIT) {
1085                 uData.msgEncoding = isAscii7bitSupportedForLongMessage()
1086                         ? UserData.ENCODING_7BIT_ASCII : UserData.ENCODING_GSM_7BIT_ALPHABET;
1087                 Rlog.d(TAG, "Message encoding for proper 7 bit: " + uData.msgEncoding);
1088             } else { // assume UTF-16
1089                 uData.msgEncoding = UserData.ENCODING_UNICODE_16;
1090             }
1091             uData.msgEncodingSet = true;
1092 
1093             /* By setting the statusReportRequested bit only for the
1094              * last message fragment, this will result in only one
1095              * callback to the sender when that last fragment delivery
1096              * has been acknowledged. */
1097             //TODO FIX
1098             SmsMessageBase.SubmitPduBase submitPdu =
1099                     com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(destinationAddress,
1100                             uData, (deliveryIntent != null) && lastPart, priority);
1101 
1102             if (submitPdu != null) {
1103                 HashMap map = getSmsTrackerMap(destinationAddress, scAddress,
1104                         message, submitPdu);
1105                 return getSmsTracker(callingPackage, map, sentIntent, deliveryIntent,
1106                         getFormat(), unsentPartCount, anyPartFailed, messageUri, smsHeader,
1107                         (!lastPart || expectMore), fullMessageText, true /*isText*/,
1108                         true /*persistMessage*/, priority, validityPeriod, false /* isForVvm */);
1109             } else {
1110                 Rlog.e(TAG, "CdmaSMSDispatcher.getNewSubmitPduTracker(): getSubmitPdu() returned "
1111                         + "null");
1112                 return null;
1113             }
1114         } else {
1115             SmsMessageBase.SubmitPduBase pdu =
1116                     com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
1117                             destinationAddress, message, deliveryIntent != null,
1118                             SmsHeader.toByteArray(smsHeader), encoding, smsHeader.languageTable,
1119                             smsHeader.languageShiftTable, validityPeriod);
1120             if (pdu != null) {
1121                 HashMap map =  getSmsTrackerMap(destinationAddress, scAddress,
1122                         message, pdu);
1123                 return getSmsTracker(callingPackage, map, sentIntent,
1124                         deliveryIntent, getFormat(), unsentPartCount, anyPartFailed, messageUri,
1125                         smsHeader, (!lastPart || expectMore), fullMessageText, true /*isText*/,
1126                         false /*persistMessage*/, priority, validityPeriod, false /* isForVvm */);
1127             } else {
1128                 Rlog.e(TAG, "GsmSMSDispatcher.getNewSubmitPduTracker(): getSubmitPdu() returned "
1129                         + "null");
1130                 return null;
1131             }
1132         }
1133     }
1134 
1135     /**
1136      * Send an SMS
1137      * @param tracker will contain:
1138      * -smsc the SMSC to send the message through, or NULL for the
1139      *  default SMSC
1140      * -pdu the raw PDU to send
1141      * -sentIntent if not NULL this <code>Intent</code> is
1142      *  broadcast when the message is successfully sent, or failed.
1143      *  The result code will be <code>Activity.RESULT_OK<code> for success,
1144      *  or one of these errors:
1145      *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
1146      *  <code>RESULT_ERROR_RADIO_OFF</code>
1147      *  <code>RESULT_ERROR_NULL_PDU</code>
1148      *  <code>RESULT_ERROR_NO_SERVICE</code>.
1149      *  The per-application based SMS control checks sentIntent. If sentIntent
1150      *  is NULL the caller will be checked against all unknown applications,
1151      *  which cause smaller number of SMS to be sent in checking period.
1152      * -deliveryIntent if not NULL this <code>Intent</code> is
1153      *  broadcast when the message is delivered to the recipient.  The
1154      *  raw pdu of the status report is in the extended data ("pdu").
1155      * -param destAddr the destination phone number (for short code confirmation)
1156      */
1157     @VisibleForTesting
sendRawPdu(SmsTracker tracker)1158     public void sendRawPdu(SmsTracker tracker) {
1159         HashMap map = tracker.getData();
1160         byte pdu[] = (byte[]) map.get(MAP_KEY_PDU);
1161 
1162         if (mSmsSendDisabled) {
1163             Rlog.e(TAG, "Device does not support sending sms.");
1164             tracker.onFailed(mContext, RESULT_ERROR_NO_SERVICE, 0/*errorCode*/);
1165             return;
1166         }
1167 
1168         if (pdu == null) {
1169             Rlog.e(TAG, "Empty PDU");
1170             tracker.onFailed(mContext, RESULT_ERROR_NULL_PDU, 0/*errorCode*/);
1171             return;
1172         }
1173 
1174         String packageName = tracker.getAppPackageName();
1175         PackageManager pm = mContext.getPackageManager();
1176 
1177         // Get package info via packagemanager
1178         PackageInfo appInfo;
1179         try {
1180             appInfo = pm.getPackageInfoAsUser(
1181                     packageName, PackageManager.GET_SIGNATURES, tracker.mUserId);
1182         } catch (PackageManager.NameNotFoundException e) {
1183             Rlog.e(TAG, "Can't get calling app package info: refusing to send SMS");
1184             tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/);
1185             return;
1186         }
1187 
1188         // checkDestination() returns true if the destination is not a premium short code or the
1189         // sending app is approved to send to short codes. Otherwise, a message is sent to our
1190         // handler with the SmsTracker to request user confirmation before sending.
1191         if (checkDestination(tracker)) {
1192             // check for excessive outgoing SMS usage by this app
1193             if (!mSmsDispatchersController.getUsageMonitor().check(
1194                     appInfo.packageName, SINGLE_PART_SMS)) {
1195                 sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, tracker));
1196                 return;
1197             }
1198 
1199             sendSms(tracker);
1200         }
1201 
1202         if (PhoneNumberUtils.isLocalEmergencyNumber(mContext, tracker.mDestAddress)) {
1203             new AsyncEmergencyContactNotifier(mContext).execute();
1204         }
1205     }
1206 
1207     /**
1208      * Check if destination is a potential premium short code and sender is not pre-approved to
1209      * send to short codes.
1210      *
1211      * @param tracker the tracker for the SMS to send
1212      * @return true if the destination is approved; false if user confirmation event was sent
1213      */
checkDestination(SmsTracker tracker)1214     boolean checkDestination(SmsTracker tracker) {
1215         if (mContext.checkCallingOrSelfPermission(SEND_SMS_NO_CONFIRMATION)
1216                 == PackageManager.PERMISSION_GRANTED || tracker.mIsForVvm) {
1217             return true;            // app is pre-approved to send to short codes
1218         } else {
1219             int rule = mPremiumSmsRule.get();
1220             int smsCategory = SmsManager.SMS_CATEGORY_NOT_SHORT_CODE;
1221             if (rule == PREMIUM_RULE_USE_SIM || rule == PREMIUM_RULE_USE_BOTH) {
1222                 String simCountryIso =
1223                         mTelephonyManager.getSimCountryIsoForPhone(mPhone.getPhoneId());
1224                 if (simCountryIso == null || simCountryIso.length() != 2) {
1225                     Rlog.e(TAG, "Can't get SIM country Iso: trying network country Iso");
1226                     simCountryIso =
1227                             mTelephonyManager.getNetworkCountryIsoForPhone(mPhone.getPhoneId());
1228                 }
1229 
1230                 smsCategory = mSmsDispatchersController.getUsageMonitor().checkDestination(
1231                         tracker.mDestAddress, simCountryIso);
1232             }
1233             if (rule == PREMIUM_RULE_USE_NETWORK || rule == PREMIUM_RULE_USE_BOTH) {
1234                 String networkCountryIso =
1235                         mTelephonyManager.getNetworkCountryIsoForPhone(mPhone.getPhoneId());
1236                 if (networkCountryIso == null || networkCountryIso.length() != 2) {
1237                     Rlog.e(TAG, "Can't get Network country Iso: trying SIM country Iso");
1238                     networkCountryIso =
1239                             mTelephonyManager.getSimCountryIsoForPhone(mPhone.getPhoneId());
1240                 }
1241 
1242                 smsCategory = SmsUsageMonitor.mergeShortCodeCategories(smsCategory,
1243                         mSmsDispatchersController.getUsageMonitor().checkDestination(
1244                                 tracker.mDestAddress, networkCountryIso));
1245             }
1246 
1247             if (smsCategory == SmsManager.SMS_CATEGORY_NOT_SHORT_CODE
1248                     || smsCategory == SmsManager.SMS_CATEGORY_FREE_SHORT_CODE
1249                     || smsCategory == SmsManager.SMS_CATEGORY_STANDARD_SHORT_CODE) {
1250                 return true;    // not a premium short code
1251             }
1252 
1253             // Do not allow any premium sms during SuW
1254             if (Settings.Global.getInt(mResolver, Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
1255                 Rlog.e(TAG, "Can't send premium sms during Setup Wizard");
1256                 return false;
1257             }
1258 
1259             // Wait for user confirmation unless the user has set permission to always allow/deny
1260             int premiumSmsPermission =
1261                     mSmsDispatchersController.getUsageMonitor().getPremiumSmsPermission(
1262                     tracker.getAppPackageName());
1263             if (premiumSmsPermission == SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) {
1264                 // First time trying to send to premium SMS.
1265                 premiumSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER;
1266             }
1267 
1268             switch (premiumSmsPermission) {
1269                 case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW:
1270                     Rlog.d(TAG, "User approved this app to send to premium SMS");
1271                     return true;
1272 
1273                 case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW:
1274                     Rlog.w(TAG, "User denied this app from sending to premium SMS");
1275                     Message msg = obtainMessage(EVENT_STOP_SENDING, tracker);
1276                     msg.arg1 = ConfirmDialogListener.SHORT_CODE_MSG;
1277                     msg.arg2 = ConfirmDialogListener.NEVER_ALLOW;
1278                     sendMessage(msg);
1279                     return false;   // reject this message
1280 
1281                 case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER:
1282                 default:
1283                     int event;
1284                     if (smsCategory == SmsManager.SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE) {
1285                         event = EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE;
1286                     } else {
1287                         event = EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE;
1288                     }
1289                     sendMessage(obtainMessage(event, tracker));
1290                     return false;   // wait for user confirmation
1291             }
1292         }
1293     }
1294 
1295     /**
1296      * Deny sending an SMS if the outgoing queue limit is reached. Used when the message
1297      * must be confirmed by the user due to excessive usage or potential premium SMS detected.
1298      * @param tracker the SmsTracker for the message to send
1299      * @return true if the message was denied; false to continue with send confirmation
1300      */
denyIfQueueLimitReached(SmsTracker tracker)1301     private boolean denyIfQueueLimitReached(SmsTracker tracker) {
1302         if (mPendingTrackerCount >= MO_MSG_QUEUE_LIMIT) {
1303             // Deny sending message when the queue limit is reached.
1304             Rlog.e(TAG, "Denied because queue limit reached");
1305             tracker.onFailed(mContext, RESULT_ERROR_LIMIT_EXCEEDED, 0/*errorCode*/);
1306             return true;
1307         }
1308         mPendingTrackerCount++;
1309         return false;
1310     }
1311 
1312     /**
1313      * Returns the label for the specified app package name.
1314      * @param appPackage the package name of the app requesting to send an SMS
1315      * @return the label for the specified app, or the package name if getApplicationInfo() fails
1316      */
getAppLabel(String appPackage, @UserIdInt int userId)1317     private CharSequence getAppLabel(String appPackage, @UserIdInt int userId) {
1318         PackageManager pm = mContext.getPackageManager();
1319         try {
1320             ApplicationInfo appInfo = pm.getApplicationInfoAsUser(appPackage, 0, userId);
1321             return appInfo.loadSafeLabel(pm, PackageItemInfo.DEFAULT_MAX_LABEL_SIZE_PX,
1322                     PackageItemInfo.SAFE_LABEL_FLAG_TRIM
1323                             | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
1324         } catch (PackageManager.NameNotFoundException e) {
1325             Rlog.e(TAG, "PackageManager Name Not Found for package " + appPackage);
1326             return appPackage;  // fall back to package name if we can't get app label
1327         }
1328     }
1329 
1330     /**
1331      * Post an alert when SMS needs confirmation due to excessive usage.
1332      * @param tracker an SmsTracker for the current message.
1333      */
handleReachSentLimit(SmsTracker tracker)1334     protected void handleReachSentLimit(SmsTracker tracker) {
1335         if (denyIfQueueLimitReached(tracker)) {
1336             return;     // queue limit reached; error was returned to caller
1337         }
1338 
1339         CharSequence appLabel = getAppLabel(tracker.getAppPackageName(), tracker.mUserId);
1340         Resources r = Resources.getSystem();
1341         Spanned messageText = Html.fromHtml(r.getString(R.string.sms_control_message, appLabel));
1342 
1343         // Construct ConfirmDialogListenter for Rate Limit handling
1344         ConfirmDialogListener listener = new ConfirmDialogListener(tracker, null,
1345                 ConfirmDialogListener.RATE_LIMIT);
1346 
1347         AlertDialog d = new AlertDialog.Builder(mContext)
1348                 .setTitle(R.string.sms_control_title)
1349                 .setIcon(R.drawable.stat_sys_warning)
1350                 .setMessage(messageText)
1351                 .setPositiveButton(r.getString(R.string.sms_control_yes), listener)
1352                 .setNegativeButton(r.getString(R.string.sms_control_no), listener)
1353                 .setOnCancelListener(listener)
1354                 .create();
1355 
1356         d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1357         d.show();
1358     }
1359 
1360     /**
1361      * Post an alert for user confirmation when sending to a potential short code.
1362      * @param isPremium true if the destination is known to be a premium short code
1363      * @param tracker the SmsTracker for the current message.
1364      */
1365     @UnsupportedAppUsage
handleConfirmShortCode(boolean isPremium, SmsTracker tracker)1366     protected void handleConfirmShortCode(boolean isPremium, SmsTracker tracker) {
1367         if (denyIfQueueLimitReached(tracker)) {
1368             return;     // queue limit reached; error was returned to caller
1369         }
1370 
1371         int detailsId;
1372         if (isPremium) {
1373             detailsId = R.string.sms_premium_short_code_details;
1374         } else {
1375             detailsId = R.string.sms_short_code_details;
1376         }
1377 
1378         CharSequence appLabel = getAppLabel(tracker.getAppPackageName(), tracker.mUserId);
1379         Resources r = Resources.getSystem();
1380         Spanned messageText = Html.fromHtml(r.getString(R.string.sms_short_code_confirm_message,
1381                 appLabel, tracker.mDestAddress));
1382 
1383         LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
1384                 Context.LAYOUT_INFLATER_SERVICE);
1385         View layout = inflater.inflate(R.layout.sms_short_code_confirmation_dialog, null);
1386 
1387         // Construct ConfirmDialogListenter for short code message sending
1388         ConfirmDialogListener listener = new ConfirmDialogListener(tracker,
1389                 (TextView) layout.findViewById(R.id.sms_short_code_remember_undo_instruction),
1390                 ConfirmDialogListener.SHORT_CODE_MSG);
1391 
1392 
1393         TextView messageView = (TextView) layout.findViewById(R.id.sms_short_code_confirm_message);
1394         messageView.setText(messageText);
1395 
1396         ViewGroup detailsLayout = (ViewGroup) layout.findViewById(
1397                 R.id.sms_short_code_detail_layout);
1398         TextView detailsView = (TextView) detailsLayout.findViewById(
1399                 R.id.sms_short_code_detail_message);
1400         detailsView.setText(detailsId);
1401 
1402         CheckBox rememberChoice = (CheckBox) layout.findViewById(
1403                 R.id.sms_short_code_remember_choice_checkbox);
1404         rememberChoice.setOnCheckedChangeListener(listener);
1405 
1406         AlertDialog d = new AlertDialog.Builder(mContext)
1407                 .setView(layout)
1408                 .setPositiveButton(r.getString(R.string.sms_short_code_confirm_allow), listener)
1409                 .setNegativeButton(r.getString(R.string.sms_short_code_confirm_deny), listener)
1410                 .setOnCancelListener(listener)
1411                 .create();
1412 
1413         d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1414         d.show();
1415 
1416         listener.setPositiveButton(d.getButton(DialogInterface.BUTTON_POSITIVE));
1417         listener.setNegativeButton(d.getButton(DialogInterface.BUTTON_NEGATIVE));
1418     }
1419 
1420     /**
1421      * Send the message along to the radio.
1422      *
1423      * @param tracker holds the SMS message to send
1424      */
1425     @UnsupportedAppUsage
sendSms(SmsTracker tracker)1426     protected abstract void sendSms(SmsTracker tracker);
1427 
1428     /**
1429      * Retry the message along to the radio.
1430      *
1431      * @param tracker holds the SMS message to send
1432      */
sendRetrySms(SmsTracker tracker)1433     public void sendRetrySms(SmsTracker tracker) {
1434         // re-routing to SmsDispatchersController
1435         if (mSmsDispatchersController != null) {
1436             mSmsDispatchersController.sendRetrySms(tracker);
1437         } else {
1438             Rlog.e(TAG, mSmsDispatchersController + " is null. Retry failed");
1439         }
1440     }
1441 
1442     /**
1443      * Send the multi-part SMS based on multipart Sms tracker
1444      *
1445      * @param tracker holds the multipart Sms tracker ready to be sent
1446      */
1447     @UnsupportedAppUsage
sendMultipartSms(SmsTracker tracker)1448     private void sendMultipartSms(SmsTracker tracker) {
1449         ArrayList<String> parts;
1450         ArrayList<PendingIntent> sentIntents;
1451         ArrayList<PendingIntent> deliveryIntents;
1452 
1453         HashMap<String, Object> map = tracker.getData();
1454 
1455         String destinationAddress = (String) map.get("destination");
1456         String scAddress = (String) map.get("scaddress");
1457 
1458         parts = (ArrayList<String>) map.get("parts");
1459         sentIntents = (ArrayList<PendingIntent>) map.get("sentIntents");
1460         deliveryIntents = (ArrayList<PendingIntent>) map.get("deliveryIntents");
1461 
1462         // check if in service
1463         int ss = mPhone.getServiceState().getState();
1464         // if sms over IMS is not supported on data and voice is not available...
1465         if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
1466             for (int i = 0, count = parts.size(); i < count; i++) {
1467                 PendingIntent sentIntent = null;
1468                 if (sentIntents != null && sentIntents.size() > i) {
1469                     sentIntent = sentIntents.get(i);
1470                 }
1471                 handleNotInService(ss, sentIntent);
1472             }
1473             return;
1474         }
1475 
1476         sendMultipartText(destinationAddress, scAddress, parts, sentIntents, deliveryIntents,
1477                 null/*messageUri*/, null/*callingPkg*/, tracker.mPersistMessage, tracker.mPriority,
1478                 tracker.mExpectMore, tracker.mValidityPeriod);
1479     }
1480 
1481     /**
1482      * Keeps track of an SMS that has been sent to the RIL, until it has
1483      * successfully been sent, or we're done trying.
1484      */
1485     public static class SmsTracker {
1486         // fields need to be public for derived SmsDispatchers
1487         @UnsupportedAppUsage
1488         private final HashMap<String, Object> mData;
1489         public int mRetryCount;
1490         // IMS retry counter. Nonzero indicates initial message was sent over IMS channel in RIL and
1491         // counts how many retries have been made on the IMS channel.
1492         // Used in older implementations where the message is sent over IMS using the RIL.
1493         public int mImsRetry;
1494         // Tag indicating that this SMS is being handled by the ImsSmsDispatcher. This tracker
1495         // should not try to use SMS over IMS over the RIL interface in this case when falling back.
1496         public boolean mUsesImsServiceForIms;
1497         @UnsupportedAppUsage
1498         public int mMessageRef;
1499         public boolean mExpectMore;
1500         public int mValidityPeriod;
1501         public int mPriority;
1502         String mFormat;
1503 
1504         @UnsupportedAppUsage
1505         public final PendingIntent mSentIntent;
1506         @UnsupportedAppUsage
1507         public final PendingIntent mDeliveryIntent;
1508 
1509         @UnsupportedAppUsage
1510         public final PackageInfo mAppInfo;
1511         @UnsupportedAppUsage
1512         public final String mDestAddress;
1513 
1514         public final SmsHeader mSmsHeader;
1515 
1516         @UnsupportedAppUsage
1517         private long mTimestamp = System.currentTimeMillis();
1518         @UnsupportedAppUsage
1519         public Uri mMessageUri; // Uri of persisted message if we wrote one
1520 
1521         // Reference to states of a multipart message that this part belongs to
1522         private AtomicInteger mUnsentPartCount;
1523         private AtomicBoolean mAnyPartFailed;
1524         // The full message content of a single part message
1525         // or a multipart message that this part belongs to
1526         private String mFullMessageText;
1527 
1528         private int mSubId;
1529 
1530         // If this is a text message (instead of data message)
1531         private boolean mIsText;
1532 
1533         @UnsupportedAppUsage
1534         private boolean mPersistMessage;
1535 
1536         // User who sends the SMS.
1537         private final @UserIdInt int mUserId;
1538 
1539         private final boolean mIsForVvm;
1540 
SmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent, PackageInfo appInfo, String destAddr, String format, AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, SmsHeader smsHeader, boolean expectMore, String fullMessageText, int subId, boolean isText, boolean persistMessage, int userId, int priority, int validityPeriod, boolean isForVvm)1541         private SmsTracker(HashMap<String, Object> data, PendingIntent sentIntent,
1542                 PendingIntent deliveryIntent, PackageInfo appInfo, String destAddr, String format,
1543                 AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
1544                 SmsHeader smsHeader, boolean expectMore, String fullMessageText, int subId,
1545                 boolean isText, boolean persistMessage, int userId, int priority,
1546                 int validityPeriod, boolean isForVvm) {
1547             mData = data;
1548             mSentIntent = sentIntent;
1549             mDeliveryIntent = deliveryIntent;
1550             mRetryCount = 0;
1551             mAppInfo = appInfo;
1552             mDestAddress = destAddr;
1553             mFormat = format;
1554             mExpectMore = expectMore;
1555             mImsRetry = 0;
1556             mUsesImsServiceForIms = false;
1557             mMessageRef = 0;
1558             mUnsentPartCount = unsentPartCount;
1559             mAnyPartFailed = anyPartFailed;
1560             mMessageUri = messageUri;
1561             mSmsHeader = smsHeader;
1562             mFullMessageText = fullMessageText;
1563             mSubId = subId;
1564             mIsText = isText;
1565             mPersistMessage = persistMessage;
1566             mUserId = userId;
1567             mPriority = priority;
1568             mValidityPeriod = validityPeriod;
1569             mIsForVvm = isForVvm;
1570         }
1571 
1572         /**
1573          * Returns whether this tracker holds a multi-part SMS.
1574          * @return true if the tracker holds a multi-part SMS; false otherwise
1575          */
1576         @UnsupportedAppUsage
isMultipart()1577         boolean isMultipart() {
1578             return mData.containsKey("parts");
1579         }
1580 
getData()1581         public HashMap<String, Object> getData() {
1582             return mData;
1583         }
1584 
1585         /**
1586          * Get the App package name
1587          * @return App package name info
1588          */
getAppPackageName()1589         public String getAppPackageName() {
1590             return mAppInfo != null ? mAppInfo.packageName : null;
1591         }
1592 
1593         /**
1594          * Update the status of this message if we persisted it
1595          */
1596         @UnsupportedAppUsage
updateSentMessageStatus(Context context, int status)1597         public void updateSentMessageStatus(Context context, int status) {
1598             if (mMessageUri != null) {
1599                 // If we wrote this message in writeSentMessage, update it now
1600                 ContentValues values = new ContentValues(1);
1601                 values.put(Sms.STATUS, status);
1602                 SqliteWrapper.update(context, context.getContentResolver(),
1603                         mMessageUri, values, null, null);
1604             }
1605         }
1606 
1607         /**
1608          * Set the final state of a message: FAILED or SENT
1609          *
1610          * @param context The Context
1611          * @param messageType The final message type
1612          * @param errorCode The error code
1613          */
updateMessageState(Context context, int messageType, int errorCode)1614         private void updateMessageState(Context context, int messageType, int errorCode) {
1615             if (mMessageUri == null) {
1616                 return;
1617             }
1618             final ContentValues values = new ContentValues(2);
1619             values.put(Sms.TYPE, messageType);
1620             values.put(Sms.ERROR_CODE, errorCode);
1621             final long identity = Binder.clearCallingIdentity();
1622             try {
1623                 if (SqliteWrapper.update(context, context.getContentResolver(), mMessageUri, values,
1624                         null/*where*/, null/*selectionArgs*/) != 1) {
1625                     Rlog.e(TAG, "Failed to move message to " + messageType);
1626                 }
1627             } finally {
1628                 Binder.restoreCallingIdentity(identity);
1629             }
1630         }
1631 
1632         /**
1633          * Persist a sent SMS if required:
1634          * 1. It is a text message
1635          * 2. SmsApplication tells us to persist: sent from apps that are not default-SMS app or
1636          *    bluetooth
1637          *
1638          * @param context
1639          * @param messageType The folder to store (FAILED or SENT)
1640          * @param errorCode The current error code for this SMS or SMS part
1641          * @return The telephony provider URI if stored
1642          */
persistSentMessageIfRequired(Context context, int messageType, int errorCode)1643         private Uri persistSentMessageIfRequired(Context context, int messageType, int errorCode) {
1644             if (!mIsText || !mPersistMessage ||
1645                     !SmsApplication.shouldWriteMessageForPackage(mAppInfo.packageName, context)) {
1646                 return null;
1647             }
1648             Rlog.d(TAG, "Persist SMS into "
1649                     + (messageType == Sms.MESSAGE_TYPE_FAILED ? "FAILED" : "SENT"));
1650             final ContentValues values = new ContentValues();
1651             values.put(Sms.SUBSCRIPTION_ID, mSubId);
1652             values.put(Sms.ADDRESS, mDestAddress);
1653             values.put(Sms.BODY, mFullMessageText);
1654             values.put(Sms.DATE, System.currentTimeMillis()); // milliseconds
1655             values.put(Sms.SEEN, 1);
1656             values.put(Sms.READ, 1);
1657             final String creator = mAppInfo != null ? mAppInfo.packageName : null;
1658             if (!TextUtils.isEmpty(creator)) {
1659                 values.put(Sms.CREATOR, creator);
1660             }
1661             if (mDeliveryIntent != null) {
1662                 values.put(Sms.STATUS, Telephony.Sms.STATUS_PENDING);
1663             }
1664             if (errorCode != 0) {
1665                 values.put(Sms.ERROR_CODE, errorCode);
1666             }
1667             final long identity = Binder.clearCallingIdentity();
1668             final ContentResolver resolver = context.getContentResolver();
1669             try {
1670                 final Uri uri =  resolver.insert(Telephony.Sms.Sent.CONTENT_URI, values);
1671                 if (uri != null && messageType == Sms.MESSAGE_TYPE_FAILED) {
1672                     // Since we can't persist a message directly into FAILED box,
1673                     // we have to update the column after we persist it into SENT box.
1674                     // The gap between the state change is tiny so I would not expect
1675                     // it to cause any serious problem
1676                     // TODO: we should add a "failed" URI for this in SmsProvider?
1677                     final ContentValues updateValues = new ContentValues(1);
1678                     updateValues.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED);
1679                     resolver.update(uri, updateValues, null/*where*/, null/*selectionArgs*/);
1680                 }
1681                 return uri;
1682             } catch (Exception e) {
1683                 Rlog.e(TAG, "writeOutboxMessage: Failed to persist outbox message", e);
1684                 return null;
1685             } finally {
1686                 Binder.restoreCallingIdentity(identity);
1687             }
1688         }
1689 
1690         /**
1691          * Persist or update an SMS depending on if we send a new message or a stored message
1692          *
1693          * @param context
1694          * @param messageType The message folder for this SMS, FAILED or SENT
1695          * @param errorCode The current error code for this SMS or SMS part
1696          */
persistOrUpdateMessage(Context context, int messageType, int errorCode)1697         private void persistOrUpdateMessage(Context context, int messageType, int errorCode) {
1698             if (mMessageUri != null) {
1699                 updateMessageState(context, messageType, errorCode);
1700             } else {
1701                 mMessageUri = persistSentMessageIfRequired(context, messageType, errorCode);
1702             }
1703         }
1704 
1705         /**
1706          * Handle a failure of a single part message or a part of a multipart message
1707          *
1708          * @param context The Context
1709          * @param error The error to send back with
1710          * @param errorCode
1711          */
1712         @UnsupportedAppUsage
onFailed(Context context, int error, int errorCode)1713         public void onFailed(Context context, int error, int errorCode) {
1714             if (mAnyPartFailed != null) {
1715                 mAnyPartFailed.set(true);
1716             }
1717             // is single part or last part of multipart message
1718             boolean isSinglePartOrLastPart = true;
1719             if (mUnsentPartCount != null) {
1720                 isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0;
1721             }
1722             if (isSinglePartOrLastPart) {
1723                 persistOrUpdateMessage(context, Sms.MESSAGE_TYPE_FAILED, errorCode);
1724             }
1725             if (mSentIntent != null) {
1726                 try {
1727                     // Extra information to send with the sent intent
1728                     Intent fillIn = new Intent();
1729                     if (mMessageUri != null) {
1730                         // Pass this to SMS apps so that they know where it is stored
1731                         fillIn.putExtra("uri", mMessageUri.toString());
1732                     }
1733                     if (errorCode != 0) {
1734                         fillIn.putExtra("errorCode", errorCode);
1735                     }
1736                     if (mUnsentPartCount != null && isSinglePartOrLastPart) {
1737                         // Is multipart and last part
1738                         fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true);
1739                     }
1740                     mSentIntent.send(context, error, fillIn);
1741                 } catch (CanceledException ex) {
1742                     Rlog.e(TAG, "Failed to send result");
1743                 }
1744             }
1745         }
1746 
1747         /**
1748          * Handle the sent of a single part message or a part of a multipart message
1749          *
1750          * @param context The Context
1751          */
1752         @UnsupportedAppUsage
onSent(Context context)1753         public void onSent(Context context) {
1754             // is single part or last part of multipart message
1755             boolean isSinglePartOrLastPart = true;
1756             if (mUnsentPartCount != null) {
1757                 isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0;
1758             }
1759             if (isSinglePartOrLastPart) {
1760                 int messageType = Sms.MESSAGE_TYPE_SENT;
1761                 if (mAnyPartFailed != null && mAnyPartFailed.get()) {
1762                     messageType = Sms.MESSAGE_TYPE_FAILED;
1763                 }
1764                 persistOrUpdateMessage(context, messageType, 0/*errorCode*/);
1765             }
1766             if (mSentIntent != null) {
1767                 try {
1768                     // Extra information to send with the sent intent
1769                     Intent fillIn = new Intent();
1770                     if (mMessageUri != null) {
1771                         // Pass this to SMS apps so that they know where it is stored
1772                         fillIn.putExtra("uri", mMessageUri.toString());
1773                     }
1774                     if (mUnsentPartCount != null && isSinglePartOrLastPart) {
1775                         // Is multipart and last part
1776                         fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true);
1777                     }
1778                     mSentIntent.send(context, Activity.RESULT_OK, fillIn);
1779                 } catch (CanceledException ex) {
1780                     Rlog.e(TAG, "Failed to send result");
1781                 }
1782             }
1783         }
1784     }
1785 
getSmsTracker(String callingPackage, HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent, String format, AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri, SmsHeader smsHeader, boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage, int priority, int validityPeriod, boolean isForVvm)1786     protected SmsTracker getSmsTracker(String callingPackage, HashMap<String, Object> data,
1787             PendingIntent sentIntent, PendingIntent deliveryIntent, String format,
1788             AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
1789             SmsHeader smsHeader, boolean expectMore, String fullMessageText, boolean isText,
1790             boolean persistMessage, int priority, int validityPeriod, boolean isForVvm) {
1791         // Get calling app package name via UID from Binder call
1792         PackageManager pm = mContext.getPackageManager();
1793 
1794         // Get package info via packagemanager
1795         final int userId = UserHandle.getCallingUserId();
1796         PackageInfo appInfo = null;
1797         try {
1798             appInfo = pm.getPackageInfoAsUser(
1799                     callingPackage, PackageManager.GET_SIGNATURES, userId);
1800         } catch (PackageManager.NameNotFoundException e) {
1801             // error will be logged in sendRawPdu
1802         }
1803         // Strip non-digits from destination phone number before checking for short codes
1804         // and before displaying the number to the user if confirmation is required.
1805         String destAddr = PhoneNumberUtils.extractNetworkPortion((String) data.get("destAddr"));
1806         return new SmsTracker(data, sentIntent, deliveryIntent, appInfo, destAddr, format,
1807                 unsentPartCount, anyPartFailed, messageUri, smsHeader, expectMore,
1808                 fullMessageText, getSubId(), isText, persistMessage, userId, priority,
1809                 validityPeriod, isForVvm);
1810     }
1811 
getSmsTracker(String callingPackage, HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent, String format, Uri messageUri, boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage, boolean isForVvm)1812     protected SmsTracker getSmsTracker(String callingPackage, HashMap<String, Object> data,
1813             PendingIntent sentIntent, PendingIntent deliveryIntent, String format, Uri messageUri,
1814             boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage,
1815             boolean isForVvm) {
1816         return getSmsTracker(callingPackage, data, sentIntent, deliveryIntent, format,
1817                 null/*unsentPartCount*/, null/*anyPartFailed*/, messageUri, null/*smsHeader*/,
1818                 expectMore, fullMessageText, isText, persistMessage,
1819                 SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, SMS_MESSAGE_PERIOD_NOT_SPECIFIED, isForVvm);
1820     }
1821 
getSmsTracker(String callingPackage, HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent, String format, Uri messageUri, boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage, int priority, int validityPeriod, boolean isForVvm)1822     protected SmsTracker getSmsTracker(String callingPackage, HashMap<String, Object> data,
1823             PendingIntent sentIntent, PendingIntent deliveryIntent, String format, Uri messageUri,
1824             boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage,
1825             int priority, int validityPeriod, boolean isForVvm) {
1826         return getSmsTracker(callingPackage, data, sentIntent, deliveryIntent, format,
1827                 null/*unsentPartCount*/, null/*anyPartFailed*/, messageUri, null/*smsHeader*/,
1828                 expectMore, fullMessageText, isText, persistMessage, priority, validityPeriod,
1829                 isForVvm);
1830     }
1831 
getSmsTrackerMap(String destAddr, String scAddr, String text, SmsMessageBase.SubmitPduBase pdu)1832     protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
1833             String text, SmsMessageBase.SubmitPduBase pdu) {
1834         HashMap<String, Object> map = new HashMap<String, Object>();
1835         map.put(MAP_KEY_DEST_ADDR, destAddr);
1836         map.put(MAP_KEY_SC_ADDR, scAddr);
1837         map.put(MAP_KEY_TEXT, text);
1838         map.put(MAP_KEY_SMSC, pdu.encodedScAddress);
1839         map.put(MAP_KEY_PDU, pdu.encodedMessage);
1840         return map;
1841     }
1842 
getSmsTrackerMap(String destAddr, String scAddr, int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu)1843     protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
1844             int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu) {
1845         HashMap<String, Object> map = new HashMap<String, Object>();
1846         map.put(MAP_KEY_DEST_ADDR, destAddr);
1847         map.put(MAP_KEY_SC_ADDR, scAddr);
1848         map.put(MAP_KEY_DEST_PORT, destPort);
1849         map.put(MAP_KEY_DATA, data);
1850         map.put(MAP_KEY_SMSC, pdu.encodedScAddress);
1851         map.put(MAP_KEY_PDU, pdu.encodedMessage);
1852         return map;
1853     }
1854 
1855     /**
1856      * Dialog listener for SMS confirmation dialog.
1857      */
1858     private final class ConfirmDialogListener
1859             implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener,
1860             CompoundButton.OnCheckedChangeListener {
1861 
1862         private final SmsTracker mTracker;
1863         @UnsupportedAppUsage
1864         private Button mPositiveButton;
1865         @UnsupportedAppUsage
1866         private Button mNegativeButton;
1867         private boolean mRememberChoice;    // default is unchecked
1868         @UnsupportedAppUsage
1869         private final TextView mRememberUndoInstruction;
1870         private int mConfirmationType;  // 0 - Short Code Msg Sending; 1 - Rate Limit Exceeded
1871         private static final int SHORT_CODE_MSG = 0; // Short Code Msg
1872         private static final int RATE_LIMIT = 1; // Rate Limit Exceeded
1873         private static final int NEVER_ALLOW = 1; // Never Allow
1874 
ConfirmDialogListener(SmsTracker tracker, TextView textView, int confirmationType)1875         ConfirmDialogListener(SmsTracker tracker, TextView textView, int confirmationType) {
1876             mTracker = tracker;
1877             mRememberUndoInstruction = textView;
1878             mConfirmationType = confirmationType;
1879         }
1880 
setPositiveButton(Button button)1881         void setPositiveButton(Button button) {
1882             mPositiveButton = button;
1883         }
1884 
setNegativeButton(Button button)1885         void setNegativeButton(Button button) {
1886             mNegativeButton = button;
1887         }
1888 
1889         @Override
onClick(DialogInterface dialog, int which)1890         public void onClick(DialogInterface dialog, int which) {
1891             // Always set the SMS permission so that Settings will show a permission setting
1892             // for the app (it won't be shown until after the app tries to send to a short code).
1893             int newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER;
1894 
1895             if (which == DialogInterface.BUTTON_POSITIVE) {
1896                 Rlog.d(TAG, "CONFIRM sending SMS");
1897                 // XXX this is lossy- apps can have more than one signature
1898                 EventLog.writeEvent(EventLogTags.EXP_DET_SMS_SENT_BY_USER,
1899                                     mTracker.mAppInfo.applicationInfo == null ?
1900                                     -1 : mTracker.mAppInfo.applicationInfo.uid);
1901                 sendMessage(obtainMessage(EVENT_SEND_CONFIRMED_SMS, mTracker));
1902                 if (mRememberChoice) {
1903                     newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW;
1904                 }
1905             } else if (which == DialogInterface.BUTTON_NEGATIVE) {
1906                 Rlog.d(TAG, "DENY sending SMS");
1907                 // XXX this is lossy- apps can have more than one signature
1908                 EventLog.writeEvent(EventLogTags.EXP_DET_SMS_DENIED_BY_USER,
1909                                     mTracker.mAppInfo.applicationInfo == null ?
1910                                     -1 :  mTracker.mAppInfo.applicationInfo.uid);
1911                 Message msg = obtainMessage(EVENT_STOP_SENDING, mTracker);
1912                 msg.arg1 = mConfirmationType;
1913                 if (mRememberChoice) {
1914                     newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW;
1915                     msg.arg2 = ConfirmDialogListener.NEVER_ALLOW;
1916                 }
1917                 sendMessage(msg);
1918             }
1919             mSmsDispatchersController.setPremiumSmsPermission(mTracker.getAppPackageName(),
1920                     newSmsPermission);
1921         }
1922 
1923         @Override
onCancel(DialogInterface dialog)1924         public void onCancel(DialogInterface dialog) {
1925             Rlog.d(TAG, "dialog dismissed: don't send SMS");
1926             Message msg = obtainMessage(EVENT_STOP_SENDING, mTracker);
1927             msg.arg1 = mConfirmationType;
1928             sendMessage(msg);
1929         }
1930 
1931         @Override
onCheckedChanged(CompoundButton buttonView, boolean isChecked)1932         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1933             Rlog.d(TAG, "remember this choice: " + isChecked);
1934             mRememberChoice = isChecked;
1935             if (isChecked) {
1936                 mPositiveButton.setText(R.string.sms_short_code_confirm_always_allow);
1937                 mNegativeButton.setText(R.string.sms_short_code_confirm_never_allow);
1938                 if (mRememberUndoInstruction != null) {
1939                     mRememberUndoInstruction.
1940                             setText(R.string.sms_short_code_remember_undo_instruction);
1941                     mRememberUndoInstruction.setPadding(0,0,0,32);
1942                 }
1943             } else {
1944                 mPositiveButton.setText(R.string.sms_short_code_confirm_allow);
1945                 mNegativeButton.setText(R.string.sms_short_code_confirm_deny);
1946                 if (mRememberUndoInstruction != null) {
1947                     mRememberUndoInstruction.setText("");
1948                     mRememberUndoInstruction.setPadding(0,0,0,0);
1949                 }
1950             }
1951         }
1952     }
1953 
isIms()1954     public boolean isIms() {
1955         if (mSmsDispatchersController != null) {
1956             return mSmsDispatchersController.isIms();
1957         } else {
1958             Rlog.e(TAG, "mSmsDispatchersController  is null");
1959             return false;
1960         }
1961     }
1962 
1963     @UnsupportedAppUsage
getMultipartMessageText(ArrayList<String> parts)1964     private String getMultipartMessageText(ArrayList<String> parts) {
1965         final StringBuilder sb = new StringBuilder();
1966         for (String part : parts) {
1967             if (part != null) {
1968                 sb.append(part);
1969             }
1970         }
1971         return sb.toString();
1972     }
1973 
1974     @UnsupportedAppUsage
getCarrierAppPackageName()1975     protected String getCarrierAppPackageName() {
1976         UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
1977         if (card == null) {
1978             return null;
1979         }
1980 
1981         List<String> carrierPackages = card.getCarrierPackageNamesForIntent(
1982             mContext.getPackageManager(), new Intent(CarrierMessagingService.SERVICE_INTERFACE));
1983         if (carrierPackages != null && carrierPackages.size() == 1) {
1984             return carrierPackages.get(0);
1985         }
1986         // If there is no carrier package which implements CarrierMessagingService, then lookup if
1987         // for a carrierImsPackage that implements CarrierMessagingService.
1988         return CarrierSmsUtils.getCarrierImsPackageForIntent(mContext, mPhone,
1989                 new Intent(CarrierMessagingService.SERVICE_INTERFACE));
1990     }
1991 
1992     @UnsupportedAppUsage
getSubId()1993     protected int getSubId() {
1994         return SubscriptionController.getInstance().getSubIdUsingPhoneId(mPhone.getPhoneId());
1995     }
1996 
1997     @UnsupportedAppUsage
checkCallerIsPhoneOrCarrierApp()1998     private void checkCallerIsPhoneOrCarrierApp() {
1999         int uid = Binder.getCallingUid();
2000         int appId = UserHandle.getAppId(uid);
2001         if (appId == Process.PHONE_UID || uid == 0) {
2002             return;
2003         }
2004         try {
2005             PackageManager pm = mContext.getPackageManager();
2006             ApplicationInfo ai = pm.getApplicationInfo(getCarrierAppPackageName(), 0);
2007             if (!UserHandle.isSameApp(ai.uid, Binder.getCallingUid())) {
2008                 throw new SecurityException("Caller is not phone or carrier app!");
2009             }
2010         } catch (PackageManager.NameNotFoundException re) {
2011             throw new SecurityException("Caller is not phone or carrier app!");
2012         }
2013     }
2014 
isCdmaMo()2015     protected boolean isCdmaMo() {
2016         return mSmsDispatchersController.isCdmaMo();
2017     }
2018 
isAscii7bitSupportedForLongMessage()2019     private boolean isAscii7bitSupportedForLongMessage() {
2020         //TODO: Do not rely on calling identity here, we should store UID & clear identity earlier.
2021         long token = Binder.clearCallingIdentity();
2022         try {
2023             CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(
2024                     Context.CARRIER_CONFIG_SERVICE);
2025             PersistableBundle pb = null;
2026             pb = configManager.getConfigForSubId(mPhone.getSubId());
2027             if (pb != null) {
2028                 return pb.getBoolean(CarrierConfigManager
2029                         .KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL);
2030             }
2031             return false;
2032         } finally {
2033             Binder.restoreCallingIdentity(token);
2034         }
2035     }
2036 }
2037