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