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 
21 import static com.android.internal.telephony.IccSmsInterfaceManager.SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
22 import static com.android.internal.telephony.IccSmsInterfaceManager.SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
23 import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
24 
25 import android.annotation.UserIdInt;
26 import android.app.Activity;
27 import android.app.AlertDialog;
28 import android.app.PendingIntent;
29 import android.app.PendingIntent.CanceledException;
30 import android.app.compat.CompatChanges;
31 import android.compat.annotation.ChangeId;
32 import android.compat.annotation.EnabledSince;
33 import android.compat.annotation.UnsupportedAppUsage;
34 import android.content.BroadcastReceiver;
35 import android.content.ContentResolver;
36 import android.content.ContentValues;
37 import android.content.Context;
38 import android.content.DialogInterface;
39 import android.content.Intent;
40 import android.content.IntentFilter;
41 import android.content.pm.ApplicationInfo;
42 import android.content.pm.PackageInfo;
43 import android.content.pm.PackageManager;
44 import android.content.res.Resources;
45 import android.content.res.Resources.NotFoundException;
46 import android.database.ContentObserver;
47 import android.net.Uri;
48 import android.os.AsyncResult;
49 import android.os.Binder;
50 import android.os.Build;
51 import android.os.Handler;
52 import android.os.Looper;
53 import android.os.Message;
54 import android.os.PersistableBundle;
55 import android.os.Process;
56 import android.os.SystemClock;
57 import android.os.UserHandle;
58 import android.provider.Settings;
59 import android.provider.Telephony;
60 import android.provider.Telephony.Sms;
61 import android.service.carrier.CarrierMessagingService;
62 import android.service.carrier.CarrierMessagingServiceWrapper;
63 import android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallback;
64 import android.telephony.AnomalyReporter;
65 import android.telephony.CarrierConfigManager;
66 import android.telephony.PhoneNumberUtils;
67 import android.telephony.ServiceState;
68 import android.telephony.SmsManager;
69 import android.telephony.SubscriptionManager;
70 import android.telephony.TelephonyManager;
71 import android.text.Html;
72 import android.text.Spanned;
73 import android.text.TextUtils;
74 import android.util.EventLog;
75 import android.util.IndentingPrintWriter;
76 import android.util.LocalLog;
77 import android.view.LayoutInflater;
78 import android.view.View;
79 import android.view.ViewGroup;
80 import android.view.WindowManager;
81 import android.widget.Button;
82 import android.widget.CheckBox;
83 import android.widget.CompoundButton;
84 import android.widget.TextView;
85 
86 import com.android.internal.R;
87 import com.android.internal.annotations.VisibleForTesting;
88 import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
89 import com.android.internal.telephony.analytics.TelephonyAnalytics;
90 import com.android.internal.telephony.analytics.TelephonyAnalytics.SmsMmsAnalytics;
91 import com.android.internal.telephony.cdma.sms.UserData;
92 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
93 import com.android.internal.telephony.subscription.SubscriptionManagerService;
94 import com.android.internal.telephony.uicc.IccRecords;
95 import com.android.internal.telephony.util.TelephonyUtils;
96 import com.android.telephony.Rlog;
97 
98 import java.io.FileDescriptor;
99 import java.io.PrintWriter;
100 import java.util.ArrayList;
101 import java.util.Arrays;
102 import java.util.HashMap;
103 import java.util.List;
104 import java.util.Random;
105 import java.util.UUID;
106 import java.util.concurrent.atomic.AtomicBoolean;
107 import java.util.concurrent.atomic.AtomicInteger;
108 
109 public abstract class SMSDispatcher extends Handler {
110     static final String TAG = "SMSDispatcher";    // accessed from inner class
111     static final boolean DBG = false;
112     private static final String SEND_NEXT_MSG_EXTRA = "SendNextMsg";
113     private static final String MESSAGE_ID_EXTRA = "MessageId";
114     protected static final String MAP_KEY_PDU = "pdu";
115     protected static final String MAP_KEY_SMSC = "smsc";
116     protected static final String MAP_KEY_DEST_ADDR = "destAddr";
117     protected static final String MAP_KEY_SC_ADDR = "scAddr";
118     protected static final String MAP_KEY_DEST_PORT = "destPort";
119     protected static final String MAP_KEY_DATA = "data";
120     protected static final String MAP_KEY_TEXT = "text";
121 
122     private static final int PREMIUM_RULE_USE_SIM = 1;
123     private static final int PREMIUM_RULE_USE_NETWORK = 2;
124     private static final int PREMIUM_RULE_USE_BOTH = 3;
125     private final AtomicInteger mPremiumSmsRule = new AtomicInteger(PREMIUM_RULE_USE_SIM);
126     private final SettingsObserver mSettingsObserver;
127 
128     /** SMS send complete. */
129     protected static final int EVENT_SEND_SMS_COMPLETE = 2;
130 
131     /** Retry sending a previously failed SMS message */
132     protected static final int EVENT_SEND_RETRY = 3;
133 
134     /** Confirmation required for sending a large number of messages. */
135     private static final int EVENT_SEND_LIMIT_REACHED_CONFIRMATION = 4;
136 
137     /** Send the user confirmed SMS */
138     static final int EVENT_SEND_CONFIRMED_SMS = 5; // accessed from inner class
139 
140     /** Don't send SMS (user did not confirm). */
141     static final int EVENT_STOP_SENDING = 6; // accessed from inner class
142 
143     /** Don't send SMS for this app (User had already denied eariler.) */
144     static final int EVENT_SENDING_NOT_ALLOWED = 7;
145 
146     /** Confirmation required for third-party apps sending to an SMS short code. */
147     private static final int EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE = 8;
148 
149     /** Confirmation required for third-party apps sending to an SMS short code. */
150     private static final int EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE = 9;
151 
152     /** New status report received. */
153     protected static final int EVENT_NEW_SMS_STATUS_REPORT = 10;
154 
155     /** Retry Sending RP-SMMA Notification */
156     protected static final int EVENT_RETRY_SMMA = 11;
157     // other
158     protected static final int EVENT_NEW_ICC_SMS = 14;
159     protected static final int EVENT_ICC_CHANGED = 15;
160     protected static final int EVENT_GET_IMS_SERVICE = 16;
161 
162     /** Last TP - Message Reference value update to SIM */
163     private static final int EVENT_TPMR_SIM_UPDATE_RESPONSE = 17;
164 
165     /** Handle SIM loaded  */
166     private static final int EVENT_SIM_LOADED = 18;
167 
168     /**
169      * When this change is enabled, more specific values of SMS sending error code
170      * {@link SmsManager#Result} will be returned to the SMS Apps.
171      *
172      * Refer to {@link SMSDispatcher#rilErrorToSmsManagerResult} fore more details of the new values
173      * of SMS sending error code that will be returned.
174      */
175     @ChangeId
176     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
177     static final long ADD_MORE_SMS_SENDING_ERROR_CODES = 250017070L;
178 
179     @UnsupportedAppUsage
180     protected Phone mPhone;
181     @UnsupportedAppUsage
182     protected final Context mContext;
183     @UnsupportedAppUsage
184     protected final ContentResolver mResolver;
185     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
186     protected final CommandsInterface mCi;
187     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
188     protected final TelephonyManager mTelephonyManager;
189     protected final LocalLog mLocalLog = new LocalLog(16);
190     protected final LocalLog mSmsOutgoingErrorCodes = new LocalLog(10);
191 
192     /** Maximum number of times to retry sending a failed SMS. */
193     protected static final int MAX_SEND_RETRIES = 3;
194 
195     /** Retransmitted Flag as specified in section 6.3.1.2 in TS 124011
196      * true:  RP-SMMA Retried once and no more transmissions are permitted
197      * false: not retried at all and at least another transmission of the RP-SMMA message
198      * is currently permitted
199      */
200     protected boolean mRPSmmaRetried = false;
201 
202     /** Delay before next send attempt on a failed SMS, in milliseconds. */
203     @VisibleForTesting
204     public static final int SEND_RETRY_DELAY = 2000;
205     /** Message sending queue limit */
206     private static final int MO_MSG_QUEUE_LIMIT = 5;
207     /** SMS anomaly uuid -- CarrierMessagingService did not respond */
208     private static final UUID sAnomalyNoResponseFromCarrierMessagingService =
209             UUID.fromString("279d9fbc-462d-4fc2-802c-bf21ddd9dd90");
210     /** SMS anomaly uuid -- CarrierMessagingService unexpected callback */
211     private static final UUID sAnomalyUnexpectedCallback =
212             UUID.fromString("0103b6d2-ad07-4d86-9102-14341b9074ef");
213 
214     /**
215      * Message reference for a CONCATENATED_8_BIT_REFERENCE or
216      * CONCATENATED_16_BIT_REFERENCE message set.  Should be
217      * incremented for each set of concatenated messages.
218      * Static field shared by all dispatcher objects.
219      */
220     private static int sConcatenatedRef = new Random().nextInt(256);
221 
222     protected SmsDispatchersController mSmsDispatchersController;
223 
224     /** Number of outgoing SmsTrackers waiting for user confirmation. */
225     private int mPendingTrackerCount;
226 
227     /* Flags indicating whether the current device allows sms service */
228     protected boolean mSmsCapable = true;
229     protected boolean mSmsSendDisabled;
230 
231     @VisibleForTesting
232     public int mCarrierMessagingTimeout = 10 * 60 * 1000; //10 minutes
233 
234     /** Used for storing last TP - Message Reference used*/
235     private int mMessageRef = -1;
236 
237     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getNextConcatenatedRef()238     protected static int getNextConcatenatedRef() {
239         sConcatenatedRef += 1;
240         return sConcatenatedRef;
241     }
242 
243     /**
244      * Create a new SMS dispatcher.
245      * @param phone the Phone to use
246      */
SMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController)247     protected SMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController) {
248         mPhone = phone;
249         mSmsDispatchersController = smsDispatchersController;
250         mContext = phone.getContext();
251         mResolver = mContext.getContentResolver();
252         mCi = phone.mCi;
253         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
254         mSettingsObserver = new SettingsObserver(this, mPremiumSmsRule, mContext);
255         mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
256                 Settings.Global.SMS_SHORT_CODE_RULE), false, mSettingsObserver);
257 
258         mSmsCapable = mContext.getResources().getBoolean(
259                 com.android.internal.R.bool.config_sms_capable);
260         mSmsSendDisabled = !mTelephonyManager.getSmsSendCapableForPhone(
261                 mPhone.getPhoneId(), mSmsCapable);
262         IntentFilter intentFilter = new IntentFilter();
263         intentFilter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
264         mContext.registerReceiver(mBroadcastReceiver, intentFilter);
265         Rlog.d(TAG, "SMSDispatcher: ctor mSmsCapable=" + mSmsCapable + " format=" + getFormat()
266                 + " mSmsSendDisabled=" + mSmsSendDisabled);
267     }
268 
269     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
270         @Override
271         public void onReceive(final Context context, Intent intent) {
272             Rlog.d(TAG, "Received broadcast " + intent.getAction());
273             if (Intent.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
274                 if (!intent.hasExtra(Intent.EXTRA_SIM_STATE)) {
275                     Rlog.d(TAG, "Extra not found in intent.");
276                 } else {
277                     String simState = intent.getStringExtra(Intent.EXTRA_SIM_STATE);
278                     if (simState.equals(Intent.SIM_STATE_LOADED)) {
279                         Rlog.d(TAG, "SIM_STATE_CHANGED : SIM_LOADED");
280                         Message msg = obtainMessage(EVENT_SIM_LOADED);
281                         msg.arg1 = getSubId();
282                         sendMessage(msg);
283                     }
284                 }
285             }
286         }
287     };
288 
289     /**
290      * Observe the secure setting for updated premium sms determination rules
291      */
292     private static class SettingsObserver extends ContentObserver {
293         private final AtomicInteger mPremiumSmsRule;
294         private final Context mContext;
SettingsObserver(Handler handler, AtomicInteger premiumSmsRule, Context context)295         SettingsObserver(Handler handler, AtomicInteger premiumSmsRule, Context context) {
296             super(handler);
297             mPremiumSmsRule = premiumSmsRule;
298             mContext = context;
299             onChange(false); // load initial value;
300         }
301 
302         @Override
onChange(boolean selfChange)303         public void onChange(boolean selfChange) {
304             mPremiumSmsRule.set(Settings.Global.getInt(mContext.getContentResolver(),
305                     Settings.Global.SMS_SHORT_CODE_RULE, PREMIUM_RULE_USE_SIM));
306         }
307     }
308 
309     /** Unregister for incoming SMS events. */
310     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
dispose()311     public void dispose() {
312         mContext.getContentResolver().unregisterContentObserver(mSettingsObserver);
313     }
314 
315     /**
316      * The format of the message PDU in the associated broadcast intent.
317      * This will be either "3gpp" for GSM/UMTS/LTE messages in 3GPP format
318      * or "3gpp2" for CDMA/LTE messages in 3GPP2 format.
319      *
320      * Note: All applications which handle incoming SMS messages by processing the
321      * SMS_RECEIVED_ACTION broadcast intent MUST pass the "format" extra from the intent
322      * into the new methods in {@link android.telephony.SmsMessage} which take an
323      * extra format parameter. This is required in order to correctly decode the PDU on
324      * devices which require support for both 3GPP and 3GPP2 formats at the same time,
325      * such as CDMA/LTE devices and GSM/CDMA world phones.
326      *
327      * @return the format of the message PDU
328      */
getFormat()329     protected abstract String getFormat();
330 
331     /**
332      * Gets the maximum number of times the SMS can be retried upon Failure,
333      * from the {@link android.telephony.CarrierConfigManager}
334      *
335      * @return the default maximum number of times SMS can be sent
336      */
getMaxSmsRetryCount()337     protected int getMaxSmsRetryCount() {
338         return MAX_SEND_RETRIES;
339     }
340 
341     /**
342      * Gets the Time delay before next send attempt on a failed SMS,
343      * from the {@link android.telephony.CarrierConfigManager}
344      *
345      * @return the Time in miiliseconds for delay before next send attempt on a failed SMS
346      */
getSmsRetryDelayValue()347     protected int getSmsRetryDelayValue() {
348         return SEND_RETRY_DELAY;
349     }
350 
351     /**
352      * Called when a status report is received. This should correspond to a previously successful
353      * SEND.
354      *
355      * @param o AsyncResult object including a byte array for 3GPP status report PDU or SmsMessage
356      *          object for 3GPP2 status report.
357      */
handleStatusReport(Object o)358     protected void handleStatusReport(Object o) {
359         Rlog.d(TAG, "handleStatusReport() called with no subclass.");
360     }
361 
362     /**
363      * Handles events coming from the phone stack. Overridden from handler.
364      *
365      * @param msg the message to handle
366      */
367     @Override
handleMessage(Message msg)368     public void handleMessage(Message msg) {
369         switch (msg.what) {
370             case EVENT_SEND_SMS_COMPLETE:
371                 // An outbound SMS has been successfully transferred, or failed.
372                 handleSendComplete((AsyncResult) msg.obj);
373                 break;
374 
375             case EVENT_SEND_RETRY:
376                 Rlog.d(TAG, "SMS retry..");
377                 sendRetrySms((SmsTracker) msg.obj);
378                 break;
379 
380             case EVENT_SEND_LIMIT_REACHED_CONFIRMATION:
381                 handleReachSentLimit((SmsTracker[]) (msg.obj));
382                 break;
383 
384             case EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE:
385                 handleConfirmShortCode(false, (SmsTracker[]) (msg.obj));
386                 break;
387 
388             case EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE:
389                 handleConfirmShortCode(true, (SmsTracker[]) (msg.obj));
390                 break;
391 
392             case EVENT_SEND_CONFIRMED_SMS: {
393                 SmsTracker[] trackers = (SmsTracker[]) msg.obj;
394                 for (SmsTracker tracker : trackers) {
395                     sendSms(tracker);
396                 }
397                 mPendingTrackerCount--;
398                 break;
399             }
400 
401             case EVENT_SENDING_NOT_ALLOWED: {
402                 SmsTracker[] trackers = (SmsTracker[]) msg.obj;
403                 Rlog.d(TAG, "SMSDispatcher: EVENT_SENDING_NOT_ALLOWED - "
404                         + "sending SHORT_CODE_NEVER_ALLOWED error code.");
405                 handleSmsTrackersFailure(
406                         trackers, SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED, NO_ERROR_CODE);
407                 break;
408             }
409 
410             case EVENT_STOP_SENDING: {
411                 SmsTracker[] trackers = (SmsTracker[]) msg.obj;
412                 int error;
413                 if (msg.arg1 == ConfirmDialogListener.SHORT_CODE_MSG) {
414                     if (msg.arg2 == ConfirmDialogListener.NEVER_ALLOW) {
415                         error = SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED;
416                         Rlog.d(TAG, "SMSDispatcher: EVENT_STOP_SENDING - "
417                                 + "sending SHORT_CODE_NEVER_ALLOWED error code.");
418                     } else {
419                         error = SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED;
420                         Rlog.d(TAG, "SMSDispatcher: EVENT_STOP_SENDING - "
421                                 + "sending SHORT_CODE_NOT_ALLOWED error code.");
422                     }
423                 } else if (msg.arg1 == ConfirmDialogListener.RATE_LIMIT) {
424                     error = SmsManager.RESULT_ERROR_LIMIT_EXCEEDED;
425                     Rlog.d(TAG, "SMSDispatcher: EVENT_STOP_SENDING - "
426                             + "sending LIMIT_EXCEEDED error code.");
427                 } else {
428                     error = SmsManager.RESULT_UNEXPECTED_EVENT_STOP_SENDING;
429                     Rlog.e(TAG, "SMSDispatcher: EVENT_STOP_SENDING - unexpected cases.");
430                 }
431 
432                 handleSmsTrackersFailure(trackers, error, NO_ERROR_CODE);
433                 mPendingTrackerCount--;
434                 break;
435             }
436 
437             case EVENT_NEW_SMS_STATUS_REPORT:
438                 handleStatusReport(msg.obj);
439                 break;
440             case EVENT_TPMR_SIM_UPDATE_RESPONSE:
441                 handleMessageRefStatus(msg);
442                 break;
443 
444             case EVENT_SIM_LOADED:
445                 /* sim TPMR value is given higher priority if both are non-negative number.
446                    Use case:
447                    if sim was used on another device and inserted in a new device,
448                    that device will start sending the next TPMR after reading from the SIM.
449                  */
450                 mMessageRef = getTpmrValueFromSIM();
451                 if (mMessageRef == -1) {
452                     SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance()
453                             .getSubscriptionInfoInternal(msg.arg1);
454                     if (subInfo != null) {
455                         mMessageRef = subInfo.getLastUsedTPMessageReference();
456                     }
457                 }
458                 break;
459 
460             default:
461                 Rlog.e(TAG, "handleMessage() ignoring message of unexpected type " + msg.what);
462         }
463     }
464 
handleMessageRefStatus(Message msg)465     private void handleMessageRefStatus(Message msg) {
466         AsyncResult ar = (AsyncResult) msg.obj;
467         if (ar.exception != null) {
468             Rlog.e(TAG, "Failed to update TP - Message reference value to SIM " + ar.exception);
469         } else {
470             Rlog.d(TAG, "TP - Message reference updated to SIM Successfully");
471         }
472     }
473 
updateTPMessageReference()474     private void updateTPMessageReference() {
475         updateSIMLastTPMRValue(mMessageRef);
476         final long identity = Binder.clearCallingIdentity();
477         try {
478             SubscriptionManagerService.getInstance()
479                     .setLastUsedTPMessageReference(getSubId(), mMessageRef);
480         } catch (SecurityException e) {
481             Rlog.e(TAG, "Security Exception caused on messageRef updation to DB " + e.getMessage());
482         } finally {
483             Binder.restoreCallingIdentity(identity);
484         }
485     }
486 
updateSIMLastTPMRValue(int messageRef)487     private void updateSIMLastTPMRValue(int messageRef) {
488         Message msg = obtainMessage(EVENT_TPMR_SIM_UPDATE_RESPONSE);
489         IccRecords iccRecords = getIccRecords();
490         if (iccRecords != null) {
491             iccRecords.setSmssTpmrValue(messageRef, msg);
492         }
493     }
494 
getTpmrValueFromSIM()495     private int getTpmrValueFromSIM() {
496         IccRecords iccRecords = getIccRecords();
497         if (iccRecords != null) {
498             return iccRecords.getSmssTpmrValue();
499         }
500         return -1;
501     }
502 
getIccRecords()503     private IccRecords getIccRecords() {
504         if (mPhone != null && mPhone.getIccRecords() != null) {
505             return mPhone.getIccRecords();
506         }
507         return null;
508     }
509 
510     /**
511      * Returns the next TP message Reference value incremented by 1 for every sms sent .
512      * once a max of 255 is reached TP message Reference is reset to 0.
513      *
514      * @return messageRef TP message Reference value
515      */
nextMessageRef()516     public int nextMessageRef() {
517         if (!isMessageRefIncrementViaTelephony()) {
518             return 0;
519         }
520 
521         mMessageRef = (mMessageRef + 1) % 256;
522         updateTPMessageReference();
523         return mMessageRef;
524     }
525 
526     /**
527      * As modem is using the last used TP-MR value present in SIM card, increment of
528      * messageRef(TP-MR) value should be prevented (config_stk_sms_send_support set to false)
529      * at telephony framework. In future, config_stk_sms_send_support flag will be enabled
530      * so that messageRef(TP-MR) increment will be done at framework side only.
531      *
532      * TODO:- Need to have new flag to control writing TP-MR value to SIM or shared prefrence.
533      */
isMessageRefIncrementViaTelephony()534     public boolean isMessageRefIncrementViaTelephony() {
535         boolean isMessageRefIncrementEnabled = false;
536         try {
537             isMessageRefIncrementEnabled = mContext.getResources().getBoolean(
538                     com.android.internal.R.bool.config_stk_sms_send_support);
539         } catch (NotFoundException e) {
540             Rlog.e(TAG, "isMessageRefIncrementViaTelephony NotFoundException Exception");
541         }
542 
543         Rlog.i(TAG, "bool.config_stk_sms_send_support= " + isMessageRefIncrementEnabled);
544         return isMessageRefIncrementEnabled;
545     }
546 
547     /**
548      * Use the carrier messaging service to send a data or text SMS.
549      */
550     protected abstract class SmsSender extends Handler {
551         private static final int EVENT_TIMEOUT = 1;
552         // Initialized in sendSmsByCarrierApp
553         protected volatile CarrierMessagingCallback mSenderCallback;
554         protected final CarrierMessagingServiceWrapper mCarrierMessagingServiceWrapper =
555                 new CarrierMessagingServiceWrapper();
556         private String mCarrierPackageName;
557 
SmsSender()558         protected SmsSender() {
559             super(Looper.getMainLooper());
560         }
561 
562         /**
563          * Bind to carrierPackageName to send message through it
564          */
sendSmsByCarrierApp(String carrierPackageName, CarrierMessagingCallback senderCallback)565         public synchronized void sendSmsByCarrierApp(String carrierPackageName,
566                 CarrierMessagingCallback senderCallback) {
567             mCarrierPackageName = carrierPackageName;
568             mSenderCallback = senderCallback;
569             if (!mCarrierMessagingServiceWrapper.bindToCarrierMessagingService(
570                     mContext, carrierPackageName, runnable -> runnable.run(),
571                     ()->onServiceReady())) {
572                 Rlog.e(TAG, "bindService() for carrier messaging service failed");
573                 onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK);
574             } else {
575                 Rlog.d(TAG, "bindService() for carrier messaging service succeeded");
576                 sendMessageDelayed(obtainMessage(EVENT_TIMEOUT), mCarrierMessagingTimeout);
577             }
578         }
579 
580         /**
581          * Callback received from mCarrierPackageName on binding to it is done.
582          * NOTE: the implementations of this method must be synchronized to make sure it does not
583          * get called before {@link #sendSmsByCarrierApp} completes and {@link #EVENT_TIMEOUT} is
584          * posted
585          */
onServiceReady()586         public abstract void onServiceReady();
587 
588         /**
589          * Method to call message send callback with passed in result and default parameters
590          */
onSendComplete(@arrierMessagingService.SendResult int result)591         public abstract void onSendComplete(@CarrierMessagingService.SendResult int result);
592 
593         /**
594          * Used to get the SmsTracker for single part messages
595          */
getSmsTracker()596         public abstract SmsTracker getSmsTracker();
597 
598         /**
599          * Used to get the SmsTrackers for multi part messages
600          */
getSmsTrackers()601         public abstract SmsTracker[] getSmsTrackers();
602 
603         @Override
handleMessage(Message msg)604         public void handleMessage(Message msg) {
605             if (msg.what == EVENT_TIMEOUT) {
606                 logWithLocalLog("handleMessage: No response from " + mCarrierPackageName
607                         + " for " + mCarrierMessagingTimeout + " ms");
608                 AnomalyReporter.reportAnomaly(sAnomalyNoResponseFromCarrierMessagingService,
609                         "No response from " + mCarrierPackageName, mPhone.getCarrierId());
610                 onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK);
611             } else {
612                 logWithLocalLog("handleMessage: received unexpected message " + msg.what);
613             }
614         }
615 
removeTimeout()616         public void removeTimeout() {
617             removeMessages(EVENT_TIMEOUT);
618         }
619     }
620 
logWithLocalLog(String logStr)621     private void logWithLocalLog(String logStr) {
622         mLocalLog.log(logStr);
623         Rlog.d(TAG, logStr);
624     }
625 
626     /**
627      * Use the carrier messaging service to send a text SMS.
628      */
629     protected final class TextSmsSender extends SmsSender {
630         private final SmsTracker mTracker;
TextSmsSender(SmsTracker tracker)631         public TextSmsSender(SmsTracker tracker) {
632             super();
633             mTracker = tracker;
634         }
635 
636         @Override
onServiceReady()637         public synchronized void onServiceReady() {
638             Rlog.d(TAG, "TextSmsSender::onServiceReady");
639             HashMap<String, Object> map = mTracker.getData();
640             String text = (String) map.get(MAP_KEY_TEXT);
641 
642             if (text != null) {
643                 try {
644                     mCarrierMessagingServiceWrapper.sendTextSms(
645                             text,
646                             getSubId(),
647                             mTracker.mDestAddress,
648                             (mTracker.mDeliveryIntent != null)
649                                     ? CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS
650                                     : 0,
651                             runnable -> runnable.run(),
652                             mSenderCallback);
653                 } catch (RuntimeException e) {
654                     Rlog.e(TAG, "TextSmsSender::onServiceReady: Exception sending the SMS: "
655                             + e.getMessage());
656                     onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK);
657                 }
658             } else {
659                 Rlog.d(TAG, "TextSmsSender::onServiceReady: text == null");
660                 onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK);
661             }
662         }
663 
664         @Override
onSendComplete(int result)665         public void onSendComplete(int result) {
666             mSenderCallback.onSendSmsComplete(result, 0 /* messageRef */);
667         }
668 
669         @Override
getSmsTracker()670         public SmsTracker getSmsTracker() {
671             return mTracker;
672         }
673 
674         @Override
getSmsTrackers()675         public SmsTracker[] getSmsTrackers() {
676             Rlog.e(TAG, "getSmsTrackers: Unexpected call for TextSmsSender");
677             return null;
678         }
679     }
680 
681     /**
682      * Use the carrier messaging service to send a data SMS.
683      */
684     protected final class DataSmsSender extends SmsSender {
685         private final SmsTracker mTracker;
DataSmsSender(SmsTracker tracker)686         public DataSmsSender(SmsTracker tracker) {
687             super();
688             mTracker = tracker;
689         }
690 
691         @Override
onServiceReady()692         public synchronized void onServiceReady() {
693             Rlog.d(TAG, "DataSmsSender::onServiceReady");
694             HashMap<String, Object> map = mTracker.getData();
695             byte[] data = (byte[]) map.get(MAP_KEY_DATA);
696             int destPort = (int) map.get(MAP_KEY_DEST_PORT);
697 
698             if (data != null) {
699                 try {
700                     mCarrierMessagingServiceWrapper.sendDataSms(
701                             data,
702                             getSubId(),
703                             mTracker.mDestAddress,
704                             destPort,
705                             (mTracker.mDeliveryIntent != null)
706                                     ? CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS
707                                     : 0,
708                             runnable -> runnable.run(),
709                             mSenderCallback);
710                 } catch (RuntimeException e) {
711                     Rlog.e(TAG, "DataSmsSender::onServiceReady: Exception sending the SMS: "
712                             + e
713                             + " " + SmsController.formatCrossStackMessageId(mTracker.mMessageId));
714                     onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK);
715                 }
716             } else {
717                 Rlog.d(TAG, "DataSmsSender::onServiceReady: data == null");
718                 onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK);
719             }
720         }
721 
722         @Override
onSendComplete(int result)723         public void onSendComplete(int result) {
724             mSenderCallback.onSendSmsComplete(result, 0 /* messageRef */);
725         }
726 
727         @Override
getSmsTracker()728         public SmsTracker getSmsTracker() {
729             return mTracker;
730         }
731 
732         @Override
getSmsTrackers()733         public SmsTracker[] getSmsTrackers() {
734             Rlog.e(TAG, "getSmsTrackers: Unexpected call for DataSmsSender");
735             return null;
736         }
737     }
738 
739     /**
740      * Callback for TextSmsSender and DataSmsSender from the carrier messaging service.
741      * Once the result is ready, the carrier messaging service connection is disposed.
742      */
743     protected final class SmsSenderCallback implements CarrierMessagingCallback {
744         private final SmsSender mSmsSender;
745         private boolean mCallbackCalled = false;
746 
SmsSenderCallback(SmsSender smsSender)747         public SmsSenderCallback(SmsSender smsSender) {
748             mSmsSender = smsSender;
749         }
750 
751         /**
752          * This method should be called only once.
753          */
754         @Override
onSendSmsComplete(int result, int messageRef)755         public void onSendSmsComplete(int result, int messageRef) {
756             Rlog.d(TAG, "onSendSmsComplete: result=" + result + " messageRef=" + messageRef);
757             if (cleanupOnSendSmsComplete("onSendSmsComplete")) {
758                 return;
759             }
760 
761             final long identity = Binder.clearCallingIdentity();
762             try {
763                 processSendSmsResponse(mSmsSender.getSmsTracker(), result, messageRef);
764             } finally {
765                 Binder.restoreCallingIdentity(identity);
766             }
767         }
768 
769         /**
770          * This method should be called only once.
771          */
772         @Override
onSendMultipartSmsComplete(int result, int[] messageRefs)773         public void onSendMultipartSmsComplete(int result, int[] messageRefs) {
774             Rlog.d(TAG, "onSendMultipartSmsComplete: result=" + result + " messageRefs="
775                     + Arrays.toString(messageRefs));
776             if (cleanupOnSendSmsComplete("onSendMultipartSmsComplete")) {
777                 return;
778             }
779 
780             final long identity = Binder.clearCallingIdentity();
781             try {
782                 processSendMultipartSmsResponse(mSmsSender.getSmsTrackers(), result, messageRefs);
783             } finally {
784                 Binder.restoreCallingIdentity(identity);
785             }
786         }
787 
cleanupOnSendSmsComplete(String callingFunction)788         private boolean cleanupOnSendSmsComplete(String callingFunction) {
789             if (mCallbackCalled) {
790                 logWithLocalLog(callingFunction + ": unexpected call");
791                 AnomalyReporter.reportAnomaly(sAnomalyUnexpectedCallback,
792                         "Unexpected " + callingFunction, mPhone.getCarrierId());
793                 return true;
794             }
795 
796             mCallbackCalled = true;
797             mSmsSender.removeTimeout();
798             mSmsSender.mCarrierMessagingServiceWrapper.disconnect();
799 
800             return false;
801         }
802 
803         @Override
onReceiveSmsComplete(int result)804         public void onReceiveSmsComplete(int result) {
805             Rlog.e(TAG, "Unexpected onReceiveSmsComplete call with result: " + result);
806         }
807 
808         @Override
onSendMmsComplete(int result, byte[] sendConfPdu)809         public void onSendMmsComplete(int result, byte[] sendConfPdu) {
810             Rlog.e(TAG, "Unexpected onSendMmsComplete call with result: " + result);
811         }
812 
813         @Override
onDownloadMmsComplete(int result)814         public void onDownloadMmsComplete(int result) {
815             Rlog.e(TAG, "Unexpected onDownloadMmsComplete call with result: " + result);
816         }
817     }
818 
819     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
processSendSmsResponse(SmsTracker tracker, int result, int messageRef)820     private void processSendSmsResponse(SmsTracker tracker, int result, int messageRef) {
821         if (tracker == null) {
822             Rlog.e(TAG, "processSendSmsResponse: null tracker");
823             return;
824         }
825 
826         SmsResponse smsResponse = new SmsResponse(messageRef, null /* ackPdu */, NO_ERROR_CODE,
827                 tracker.mMessageId);
828 
829         switch (result) {
830             case CarrierMessagingService.SEND_STATUS_OK:
831                 Rlog.d(TAG, "processSendSmsResponse: Sending SMS by CarrierMessagingService "
832                         + "succeeded. "
833                         + SmsController.formatCrossStackMessageId(tracker.mMessageId));
834                 sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE,
835                                           new AsyncResult(tracker,
836                                                           smsResponse,
837                                                           null /* exception*/)));
838                 break;
839             case CarrierMessagingService.SEND_STATUS_ERROR:
840                 Rlog.d(TAG, "processSendSmsResponse: Sending SMS by CarrierMessagingService"
841                         + " failed. "
842                         + SmsController.formatCrossStackMessageId(tracker.mMessageId));
843                 sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE,
844                         new AsyncResult(tracker, smsResponse,
845                                 new CommandException(CommandException.Error.GENERIC_FAILURE))));
846                 break;
847             case CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK:
848                 Rlog.d(TAG, "processSendSmsResponse: Sending SMS by CarrierMessagingService failed."
849                         + " Retry on carrier network. "
850                         + SmsController.formatCrossStackMessageId(tracker.mMessageId));
851                 sendSubmitPdu(tracker);
852                 break;
853             default:
854                 Rlog.d(TAG, "processSendSmsResponse: Unknown result " + result + " Retry on carrier"
855                         + " network. "
856                         + SmsController.formatCrossStackMessageId(tracker.mMessageId));
857                 sendSubmitPdu(tracker);
858         }
859     }
860 
861     /**
862      * Use the carrier messaging service to send a multipart text SMS.
863      */
864     private final class MultipartSmsSender extends SmsSender {
865         private final List<String> mParts;
866         public final SmsTracker[] mTrackers;
867 
MultipartSmsSender(ArrayList<String> parts, SmsTracker[] trackers)868         MultipartSmsSender(ArrayList<String> parts, SmsTracker[] trackers) {
869             super();
870             mParts = parts;
871             mTrackers = trackers;
872         }
873 
874         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
sendSmsByCarrierApp(String carrierPackageName, SmsSenderCallback senderCallback)875         void sendSmsByCarrierApp(String carrierPackageName, SmsSenderCallback senderCallback) {
876             super.sendSmsByCarrierApp(carrierPackageName, senderCallback);
877         }
878 
879         @Override
onServiceReady()880         public synchronized void onServiceReady() {
881             Rlog.d(TAG, "MultipartSmsSender::onServiceReady");
882             boolean statusReportRequested = false;
883             for (SmsTracker tracker : mTrackers) {
884                 if (tracker.mDeliveryIntent != null) {
885                     statusReportRequested = true;
886                     break;
887                 }
888             }
889 
890             try {
891                 mCarrierMessagingServiceWrapper.sendMultipartTextSms(
892                         mParts,
893                         getSubId(),
894                         mTrackers[0].mDestAddress,
895                         statusReportRequested
896                                 ? CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS
897                                 : 0,
898                         runnable -> runnable.run(),
899                         mSenderCallback);
900             } catch (RuntimeException e) {
901                 Rlog.e(TAG, "MultipartSmsSender::onServiceReady: Exception sending the SMS: " + e);
902                 onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK);
903             }
904         }
905 
906         @Override
onSendComplete(int result)907         public void onSendComplete(int result) {
908             mSenderCallback.onSendMultipartSmsComplete(result, null /* messageRefs */);
909         }
910 
911         @Override
getSmsTracker()912         public SmsTracker getSmsTracker() {
913             Rlog.e(TAG, "getSmsTracker: Unexpected call for MultipartSmsSender");
914             return null;
915         }
916 
917         @Override
getSmsTrackers()918         public SmsTracker[] getSmsTrackers() {
919             return mTrackers;
920         }
921     }
922 
processSendMultipartSmsResponse( SmsTracker[] trackers, int result, int[] messageRefs)923     private void processSendMultipartSmsResponse(
924             SmsTracker[] trackers, int result, int[] messageRefs) {
925         if (trackers == null) {
926             Rlog.e(TAG, "processSendMultipartSmsResponse: null trackers");
927             return;
928         }
929 
930         switch (result) {
931             case CarrierMessagingService.SEND_STATUS_OK:
932                 Rlog.d(TAG, "processSendMultipartSmsResponse: Sending SMS by "
933                         + "CarrierMessagingService succeeded. "
934                         + SmsController.formatCrossStackMessageId(trackers[0].mMessageId));
935                 // Sending a multi-part SMS by CarrierMessagingService successfully completed.
936                 // Send EVENT_SEND_SMS_COMPLETE for all the parts one by one.
937                 for (int i = 0; i < trackers.length; i++) {
938                     int messageRef = 0;
939                     if (messageRefs != null && messageRefs.length > i) {
940                         messageRef = messageRefs[i];
941                     }
942                     sendMessage(
943                             obtainMessage(
944                                     EVENT_SEND_SMS_COMPLETE,
945                                     new AsyncResult(
946                                             trackers[i],
947                                             new SmsResponse(
948                                                     messageRef, null /* ackPdu */, NO_ERROR_CODE),
949                                             null /* exception */)));
950                 }
951                 break;
952             case CarrierMessagingService.SEND_STATUS_ERROR:
953                 Rlog.d(TAG, "processSendMultipartSmsResponse: Sending SMS by "
954                         + "CarrierMessagingService failed. "
955                         + SmsController.formatCrossStackMessageId(trackers[0].mMessageId));
956                 // Sending a multi-part SMS by CarrierMessagingService failed.
957                 // Send EVENT_SEND_SMS_COMPLETE with GENERIC_FAILURE for all the parts one by one.
958                 for (int i = 0; i < trackers.length; i++) {
959                     int messageRef = 0;
960                     if (messageRefs != null && messageRefs.length > i) {
961                         messageRef = messageRefs[i];
962                     }
963                     sendMessage(
964                             obtainMessage(
965                                     EVENT_SEND_SMS_COMPLETE,
966                                     new AsyncResult(
967                                             trackers[i],
968                                             new SmsResponse(
969                                                     messageRef, null /* ackPdu */, NO_ERROR_CODE),
970                                             new CommandException(
971                                                     CommandException.Error.GENERIC_FAILURE))));
972                 }
973                 break;
974             case CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK:
975                 Rlog.d(TAG, "processSendMultipartSmsResponse: Sending SMS by "
976                         + "CarrierMessagingService failed. Retry on carrier network. "
977                         + SmsController.formatCrossStackMessageId(trackers[0].mMessageId));
978                 // All the parts for a multi-part SMS are handled together for retry. It helps to
979                 // check user confirmation once also if needed.
980                 sendSubmitPdu(trackers);
981                 break;
982             default:
983                 Rlog.d(TAG, "processSendMultipartSmsResponse: Unknown result " + result
984                         + ". Retry on carrier network. "
985                         + SmsController.formatCrossStackMessageId(trackers[0].mMessageId));
986                 sendSubmitPdu(trackers);
987         }
988     }
989 
990     /** Send a single SMS PDU. */
991     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
sendSubmitPdu(SmsTracker tracker)992     private void sendSubmitPdu(SmsTracker tracker) {
993         sendSubmitPdu(new SmsTracker[] {tracker});
994     }
995 
996     /** Send a multi-part SMS PDU. Usually just calls {@link sendRawPdu}. */
sendSubmitPdu(SmsTracker[] trackers)997     private void sendSubmitPdu(SmsTracker[] trackers) {
998         if (shouldBlockSmsForEcbm()) {
999             Rlog.d(TAG, "Block SMS in Emergency Callback mode");
1000             handleSmsTrackersFailure(trackers, SmsManager.RESULT_SMS_BLOCKED_DURING_EMERGENCY,
1001                     NO_ERROR_CODE);
1002         } else {
1003             sendRawPdu(trackers);
1004         }
1005     }
1006 
1007     /**
1008      * @return true if MO SMS should be blocked for Emergency Callback Mode.
1009      */
shouldBlockSmsForEcbm()1010     protected abstract boolean shouldBlockSmsForEcbm();
1011 
1012     /**
1013      * Notifies the {@link SmsDispatchersController} that sending MO SMS is failed.
1014      *
1015      * @param tracker holds the SMS message to be sent
1016      * @param isOverIms a flag specifying whether SMS is sent via IMS or not
1017      */
notifySmsSentFailedToEmergencyStateTracker(SmsTracker tracker, boolean isOverIms)1018     protected void notifySmsSentFailedToEmergencyStateTracker(SmsTracker tracker,
1019             boolean isOverIms) {
1020         mSmsDispatchersController.notifySmsSentFailedToEmergencyStateTracker(
1021                 tracker.mDestAddress, tracker.mMessageId, isOverIms);
1022     }
1023 
1024     /**
1025      * Called when SMS send completes. Broadcasts a sentIntent on success.
1026      * On failure, either sets up retries or broadcasts a sentIntent with
1027      * the failure in the result code.
1028      *
1029      * @param ar AsyncResult passed into the message handler.  ar.result should
1030      *           an SmsResponse instance if send was successful.  ar.userObj
1031      *           should be an SmsTracker instance.
1032      */
handleSendComplete(AsyncResult ar)1033     protected void handleSendComplete(AsyncResult ar) {
1034         SmsTracker tracker = (SmsTracker) ar.userObj;
1035         PendingIntent sentIntent = tracker.mSentIntent;
1036         SmsResponse smsResponse = (SmsResponse) ar.result;
1037 
1038         if (smsResponse != null) {
1039             tracker.mMessageRef = smsResponse.mMessageRef;
1040         } else {
1041             Rlog.d(TAG, "SmsResponse was null");
1042         }
1043 
1044         if (ar.exception == null) {
1045             if (DBG) {
1046                 Rlog.d(TAG, "SMS send complete. Broadcasting intent: " + sentIntent
1047                         + " " + SmsController.formatCrossStackMessageId(tracker.mMessageId));
1048             }
1049 
1050             if (tracker.mDeliveryIntent != null) {
1051                 // Expecting a status report. Put this tracker to the map.
1052                 mSmsDispatchersController.putDeliveryPendingTracker(tracker);
1053             }
1054             tracker.onSent(mContext);
1055             mPhone.notifySmsSent(tracker.mDestAddress);
1056             mSmsDispatchersController.notifySmsSentToEmergencyStateTracker(
1057                     tracker.mDestAddress, tracker.mMessageId, false,
1058                     tracker.isSinglePartOrLastPart());
1059 
1060             mPhone.getSmsStats().onOutgoingSms(
1061                     tracker.mImsRetry > 0 /* isOverIms */,
1062                     SmsConstants.FORMAT_3GPP2.equals(getFormat()),
1063                     false /* fallbackToCs */,
1064                     SmsManager.RESULT_ERROR_NONE,
1065                     tracker.mMessageId,
1066                     tracker.isFromDefaultSmsApplication(mContext),
1067                     tracker.getInterval(),
1068                     mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
1069             if (mPhone != null) {
1070                 TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
1071                 if (telephonyAnalytics != null) {
1072                     SmsMmsAnalytics smsMmsAnalytics = telephonyAnalytics.getSmsMmsAnalytics();
1073                     if (smsMmsAnalytics != null) {
1074                         smsMmsAnalytics.onOutgoingSms(
1075                                 tracker.mImsRetry > 0 /* isOverIms */,
1076                                 SmsManager.RESULT_ERROR_NONE
1077                         );
1078                     }
1079                 }
1080             }
1081 
1082         } else {
1083             if (DBG) {
1084                 Rlog.d(TAG, "SMS send failed "
1085                         + SmsController.formatCrossStackMessageId(tracker.mMessageId));
1086             }
1087 
1088             int ss = mPhone.getServiceState().getState();
1089             int error = rilErrorToSmsManagerResult(
1090                     ((CommandException) (ar.exception)).getCommandError(), tracker);
1091 
1092             if (tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) {
1093                 // This is retry after failure over IMS but voice is not available.
1094                 // Set retry to max allowed, so no retry is sent and cause
1095                 // SmsManager.RESULT_ERROR_GENERIC_FAILURE to be returned to app.
1096                 tracker.mRetryCount = getMaxSmsRetryCount();
1097 
1098                 Rlog.d(TAG, "handleSendComplete: Skipping retry: "
1099                         + " isIms()=" + isIms()
1100                         + " mRetryCount=" + tracker.mRetryCount
1101                         + " mImsRetry=" + tracker.mImsRetry
1102                         + " mMessageRef=" + tracker.mMessageRef
1103                         + " SS= " + mPhone.getServiceState().getState()
1104                         + " " + SmsController.formatCrossStackMessageId(tracker.mMessageId));
1105             }
1106 
1107             // if sms over IMS is not supported on data and voice is not available...
1108             if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
1109                 tracker.onFailed(mContext, getNotInServiceError(ss), NO_ERROR_CODE);
1110                 notifySmsSentFailedToEmergencyStateTracker(tracker, false);
1111                 mPhone.getSmsStats().onOutgoingSms(
1112                         tracker.mImsRetry > 0 /* isOverIms */,
1113                         SmsConstants.FORMAT_3GPP2.equals(getFormat()),
1114                         false /* fallbackToCs */,
1115                         getNotInServiceError(ss),
1116                         tracker.mMessageId,
1117                         tracker.isFromDefaultSmsApplication(mContext),
1118                         tracker.getInterval(),
1119                         mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
1120                 if (mPhone != null) {
1121                     TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
1122                     if (telephonyAnalytics != null) {
1123                         SmsMmsAnalytics smsMmsAnalytics = telephonyAnalytics.getSmsMmsAnalytics();
1124                         if (smsMmsAnalytics != null) {
1125                             smsMmsAnalytics.onOutgoingSms(
1126                                     tracker.mImsRetry > 0 /* isOverIms */,
1127                                     getNotInServiceError(ss)
1128                             );
1129                         }
1130                     }
1131                 }
1132 
1133             } else if (error == SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY
1134                     && tracker.mRetryCount < getMaxSmsRetryCount()) {
1135                 // Retry after a delay if needed.
1136                 // TODO: According to TS 23.040, 9.2.3.6, we should resend
1137                 //       with the same TP-MR as the failed message, and
1138                 //       TP-RD set to 1.  However, we don't have a means of
1139                 //       knowing the MR for the failed message (EF_SMSstatus
1140                 //       may or may not have the MR corresponding to this
1141                 //       message, depending on the failure).  Also, in some
1142                 //       implementations this retry is handled by the baseband.
1143                 tracker.mRetryCount++;
1144                 int errorCode = (smsResponse != null) ? smsResponse.mErrorCode : NO_ERROR_CODE;
1145                 Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker);
1146                 sendMessageDelayed(retryMsg, getSmsRetryDelayValue());
1147                 mPhone.getSmsStats().onOutgoingSms(
1148                         tracker.mImsRetry > 0 /* isOverIms */,
1149                         SmsConstants.FORMAT_3GPP2.equals(getFormat()),
1150                         false /* fallbackToCs */,
1151                         SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY,
1152                         errorCode,
1153                         tracker.mMessageId,
1154                         tracker.isFromDefaultSmsApplication(mContext),
1155                         tracker.getInterval(),
1156                         mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
1157                 if (mPhone != null) {
1158                     TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
1159                     if (telephonyAnalytics != null) {
1160                         SmsMmsAnalytics smsMmsAnalytics = telephonyAnalytics.getSmsMmsAnalytics();
1161                         if (smsMmsAnalytics != null) {
1162                             smsMmsAnalytics.onOutgoingSms(
1163                                     tracker.mImsRetry > 0 /* isOverIms */,
1164                                     SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY
1165                             );
1166                         }
1167                     }
1168                 }
1169 
1170             } else {
1171                 int errorCode = (smsResponse != null) ? smsResponse.mErrorCode : NO_ERROR_CODE;
1172                 tracker.onFailed(mContext, error, errorCode);
1173                 notifySmsSentFailedToEmergencyStateTracker(tracker, false);
1174                 mPhone.getSmsStats().onOutgoingSms(
1175                         tracker.mImsRetry > 0 /* isOverIms */,
1176                         SmsConstants.FORMAT_3GPP2.equals(getFormat()),
1177                         false /* fallbackToCs */,
1178                         error,
1179                         errorCode,
1180                         tracker.mMessageId,
1181                         tracker.isFromDefaultSmsApplication(mContext),
1182                         tracker.getInterval(),
1183                         mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
1184                 if (mPhone != null) {
1185                     TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
1186                     if (telephonyAnalytics != null) {
1187                         SmsMmsAnalytics smsMmsAnalytics = telephonyAnalytics.getSmsMmsAnalytics();
1188                         if (smsMmsAnalytics != null) {
1189                             smsMmsAnalytics.onOutgoingSms(
1190                                     tracker.mImsRetry > 0 /* isOverIms */,
1191                                     error);
1192                         }
1193                     }
1194                 }
1195             }
1196         }
1197     }
1198 
1199     @SmsManager.Result
rilErrorToSmsManagerResult(CommandException.Error rilError, SmsTracker tracker)1200     private int rilErrorToSmsManagerResult(CommandException.Error rilError,
1201             SmsTracker tracker) {
1202         mSmsOutgoingErrorCodes.log("rilError: " + rilError
1203                 + ", MessageId: " + SmsController.formatCrossStackMessageId(tracker.mMessageId));
1204 
1205         ApplicationInfo appInfo = tracker.getAppInfo();
1206         if (appInfo == null
1207                 || !CompatChanges.isChangeEnabled(ADD_MORE_SMS_SENDING_ERROR_CODES, appInfo.uid)) {
1208             if (rilError == CommandException.Error.INVALID_RESPONSE
1209                     || rilError == CommandException.Error.SIM_PIN2
1210                     || rilError == CommandException.Error.SIM_PUK2
1211                     || rilError == CommandException.Error.SUBSCRIPTION_NOT_AVAILABLE
1212                     || rilError == CommandException.Error.SIM_ERR
1213                     || rilError == CommandException.Error.INVALID_SIM_STATE
1214                     || rilError == CommandException.Error.NO_SMS_TO_ACK
1215                     || rilError == CommandException.Error.SIM_BUSY
1216                     || rilError == CommandException.Error.SIM_FULL
1217                     || rilError == CommandException.Error.NO_SUBSCRIPTION
1218                     || rilError == CommandException.Error.NO_NETWORK_FOUND
1219                     || rilError == CommandException.Error.DEVICE_IN_USE
1220                     || rilError == CommandException.Error.ABORTED) {
1221                 return SmsManager.RESULT_ERROR_GENERIC_FAILURE;
1222             }
1223         }
1224 
1225         switch (rilError) {
1226             case RADIO_NOT_AVAILABLE:
1227                 return SmsManager.RESULT_RIL_RADIO_NOT_AVAILABLE;
1228             case SMS_FAIL_RETRY:
1229                 return SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY;
1230             case NETWORK_REJECT:
1231                 return SmsManager.RESULT_RIL_NETWORK_REJECT;
1232             case INVALID_STATE:
1233                 return SmsManager.RESULT_RIL_INVALID_STATE;
1234             case INVALID_ARGUMENTS:
1235                 return SmsManager.RESULT_RIL_INVALID_ARGUMENTS;
1236             case NO_MEMORY:
1237                 return SmsManager.RESULT_RIL_NO_MEMORY;
1238             case REQUEST_RATE_LIMITED:
1239                 return SmsManager.RESULT_RIL_REQUEST_RATE_LIMITED;
1240             case INVALID_SMS_FORMAT:
1241                 return SmsManager.RESULT_RIL_INVALID_SMS_FORMAT;
1242             case SYSTEM_ERR:
1243                 return SmsManager.RESULT_RIL_SYSTEM_ERR;
1244             case ENCODING_ERR:
1245                 return SmsManager.RESULT_RIL_ENCODING_ERR;
1246             case MODEM_ERR:
1247                 return SmsManager.RESULT_RIL_MODEM_ERR;
1248             case NETWORK_ERR:
1249                 return SmsManager.RESULT_RIL_NETWORK_ERR;
1250             case INTERNAL_ERR:
1251                 return SmsManager.RESULT_RIL_INTERNAL_ERR;
1252             case REQUEST_NOT_SUPPORTED:
1253                 return SmsManager.RESULT_RIL_REQUEST_NOT_SUPPORTED;
1254             case INVALID_MODEM_STATE:
1255                 return SmsManager.RESULT_RIL_INVALID_MODEM_STATE;
1256             case NETWORK_NOT_READY:
1257                 return SmsManager.RESULT_RIL_NETWORK_NOT_READY;
1258             case OPERATION_NOT_ALLOWED:
1259                 return SmsManager.RESULT_RIL_OPERATION_NOT_ALLOWED;
1260             case NO_RESOURCES:
1261                 return SmsManager.RESULT_RIL_NO_RESOURCES;
1262             case REQUEST_CANCELLED:
1263                 return SmsManager.RESULT_RIL_CANCELLED;
1264             case SIM_ABSENT:
1265                 return SmsManager.RESULT_RIL_SIM_ABSENT;
1266             case FDN_CHECK_FAILURE:
1267                 return SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE;
1268             case SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED:
1269                 return SmsManager.RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED;
1270             case ACCESS_BARRED:
1271                 return SmsManager.RESULT_RIL_ACCESS_BARRED;
1272             case BLOCKED_DUE_TO_CALL:
1273                 return SmsManager.RESULT_RIL_BLOCKED_DUE_TO_CALL;
1274             case INVALID_SMSC_ADDRESS:
1275                 return SmsManager.RESULT_INVALID_SMSC_ADDRESS;
1276             case INVALID_RESPONSE:
1277                 return SmsManager.RESULT_RIL_INVALID_RESPONSE;
1278             case SIM_PIN2:
1279                 return SmsManager.RESULT_RIL_SIM_PIN2;
1280             case SIM_PUK2:
1281                 return SmsManager.RESULT_RIL_SIM_PUK2;
1282             case SUBSCRIPTION_NOT_AVAILABLE:
1283                 return SmsManager.RESULT_RIL_SUBSCRIPTION_NOT_AVAILABLE;
1284             case SIM_ERR:
1285                 return SmsManager.RESULT_RIL_SIM_ERROR;
1286             case INVALID_SIM_STATE:
1287                 return SmsManager.RESULT_RIL_INVALID_SIM_STATE;
1288             case NO_SMS_TO_ACK:
1289                 return SmsManager.RESULT_RIL_NO_SMS_TO_ACK;
1290             case SIM_BUSY:
1291                 return SmsManager.RESULT_RIL_SIM_BUSY;
1292             case SIM_FULL:
1293                 return SmsManager.RESULT_RIL_SIM_FULL;
1294             case NO_SUBSCRIPTION:
1295                 return SmsManager.RESULT_RIL_NO_SUBSCRIPTION;
1296             case NO_NETWORK_FOUND:
1297                 return SmsManager.RESULT_RIL_NO_NETWORK_FOUND;
1298             case DEVICE_IN_USE:
1299                 return SmsManager.RESULT_RIL_DEVICE_IN_USE;
1300             case ABORTED:
1301                 return SmsManager.RESULT_RIL_ABORTED;
1302             default:
1303                 Rlog.d(TAG, "rilErrorToSmsManagerResult: " + rilError + " "
1304                         + SmsController.formatCrossStackMessageId(tracker.mMessageId));
1305                 return SmsManager.RESULT_RIL_GENERIC_ERROR;
1306         }
1307     }
1308 
1309     /**
1310      * @param ss service state
1311      * @return The result error based on input service state for not in service error
1312      */
1313     @SmsManager.Result
getNotInServiceError(int ss)1314     protected static int getNotInServiceError(int ss) {
1315         if (ss == ServiceState.STATE_POWER_OFF) {
1316             return SmsManager.RESULT_ERROR_RADIO_OFF;
1317         }
1318         return SmsManager.RESULT_ERROR_NO_SERVICE;
1319     }
1320 
1321     /**
1322      * Send a data based SMS to a specific application port.
1323      *
1324      * @param callingPackage the package name of the calling app
1325      * @param destAddr the address to send the message to
1326      * @param scAddr is the service center address or null to use
1327      *  the current default SMSC
1328      * @param destPort the port to deliver the message to
1329      * @param data the body of the message to send
1330      * @param sentIntent if not NULL this <code>PendingIntent</code> is
1331      *  broadcast when the message is successfully sent, or failed.
1332      *  The result code will be <code>Activity.RESULT_OK<code> for success,
1333      *  or one of these errors:<br>
1334      *  <code>SmsManager.RESULT_ERROR_GENERIC_FAILURE</code><br>
1335      *  <code>SmsManager.RESULT_ERROR_RADIO_OFF</code><br>
1336      *  <code>SmsManager.RESULT_ERROR_NULL_PDU</code><br>
1337      *  <code>SmsManager.RESULT_ERROR_NO_SERVICE</code><br>
1338      *  <code>SmsManager.RESULT_ERROR_LIMIT_EXCEEDED</code><br>
1339      *  <code>SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE</code><br>
1340      *  <code>SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br>
1341      *  <code>SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br>
1342      *  <code>SmsManager.RESULT_RADIO_NOT_AVAILABLE</code><br>
1343      *  <code>SmsManager.RESULT_NETWORK_REJECT</code><br>
1344      *  <code>SmsManager.RESULT_INVALID_ARGUMENTS</code><br>
1345      *  <code>SmsManager.RESULT_INVALID_STATE</code><br>
1346      *  <code>SmsManager.RESULT_NO_MEMORY</code><br>
1347      *  <code>SmsManager.RESULT_INVALID_SMS_FORMAT</code><br>
1348      *  <code>SmsManager.RESULT_SYSTEM_ERROR</code><br>
1349      *  <code>SmsManager.RESULT_MODEM_ERROR</code><br>
1350      *  <code>SmsManager.RESULT_NETWORK_ERROR</code><br>
1351      *  <code>SmsManager.RESULT_ENCODING_ERROR</code><br>
1352      *  <code>SmsManager.RESULT_INVALID_SMSC_ADDRESS</code><br>
1353      *  <code>SmsManager.RESULT_OPERATION_NOT_ALLOWED</code><br>
1354      *  <code>SmsManager.RESULT_INTERNAL_ERROR</code><br>
1355      *  <code>SmsManager.RESULT_NO_RESOURCES</code><br>
1356      *  <code>SmsManager.RESULT_CANCELLED</code><br>
1357      *  <code>SmsManager.RESULT_REQUEST_NOT_SUPPORTED</code><br>
1358      *  <code>SmsManager.RESULT_NO_BLUETOOTH_SERVICE</code><br>
1359      *  <code>SmsManager.RESULT_INVALID_BLUETOOTH_ADDRESS</code><br>
1360      *  <code>SmsManager.RESULT_BLUETOOTH_DISCONNECTED</code><br>
1361      *  <code>SmsManager.RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br>
1362      *  <code>SmsManager.RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br>
1363      *  <code>SmsManager.RESULT_SMS_SEND_RETRY_FAILED</code><br>
1364      *  <code>SmsManager.RESULT_REMOTE_EXCEPTION</code><br>
1365      *  <code>SmsManager.RESULT_NO_DEFAULT_SMS_APP</code><br>
1366      *  <code>SmsManager.RESULT_RIL_RADIO_NOT_AVAILABLE</code><br>
1367      *  <code>SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br>
1368      *  <code>SmsManager.RESULT_RIL_NETWORK_REJECT</code><br>
1369      *  <code>SmsManager.RESULT_RIL_INVALID_STATE</code><br>
1370      *  <code>SmsManager.RESULT_RIL_INVALID_ARGUMENTS</code><br>
1371      *  <code>SmsManager.RESULT_RIL_NO_MEMORY</code><br>
1372      *  <code>SmsManager.RESULT_RIL_REQUEST_RATE_LIMITED</code><br>
1373      *  <code>SmsManager.RESULT_RIL_INVALID_SMS_FORMAT</code><br>
1374      *  <code>SmsManager.RESULT_RIL_SYSTEM_ERR</code><br>
1375      *  <code>SmsManager.RESULT_RIL_ENCODING_ERR</code><br>
1376      *  <code>SmsManager.RESULT_RIL_INVALID_SMSC_ADDRESS</code><br>
1377      *  <code>SmsManager.RESULT_RIL_MODEM_ERR</code><br>
1378      *  <code>SmsManager.RESULT_RIL_NETWORK_ERR</code><br>
1379      *  <code>SmsManager.RESULT_RIL_INTERNAL_ERR</code><br>
1380      *  <code>SmsManager.RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br>
1381      *  <code>SmsManager.RESULT_RIL_INVALID_MODEM_STATE</code><br>
1382      *  <code>SmsManager.RESULT_RIL_NETWORK_NOT_READY</code><br>
1383      *  <code>SmsManager.RESULT_RIL_OPERATION_NOT_ALLOWED</code><br>
1384      *  <code>SmsManager.RESULT_RIL_NO_RESOURCES</code><br>
1385      *  <code>SmsManager.RESULT_RIL_CANCELLED</code><br>
1386      *  <code>SmsManager.RESULT_RIL_SIM_ABSENT</code><br>
1387      *  <code>SmsManager.RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED</code><br>
1388      *  <code>SmsManager.RESULT_RIL_ACCESS_BARRED</code><br>
1389      *  <code>SmsManager.RESULT_RIL_BLOCKED_DUE_TO_CALL</code><br>
1390      *  For <code>SmsManager.RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors,
1391      *  the sentIntent may include the extra "errorCode" containing a radio technology specific
1392      *  value, generally only useful for troubleshooting.<br>
1393      *  The per-application based SMS control checks sentIntent. If sentIntent
1394      *  is NULL the caller will be checked against all unknown applications,
1395      *  which cause smaller number of SMS to be sent in checking period.
1396      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
1397      *  broadcast when the message is delivered to the recipient.  The
1398      *  raw pdu of the status report is in the extended data ("pdu").
1399      */
1400     @UnsupportedAppUsage
sendData(String callingPackage, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm)1401     protected void sendData(String callingPackage, String destAddr, String scAddr, int destPort,
1402             byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm) {
1403         int messageRef = nextMessageRef();
1404         SmsMessageBase.SubmitPduBase pdu = getSubmitPdu(
1405                 scAddr, destAddr, destPort, data, (deliveryIntent != null), messageRef);
1406         if (pdu != null) {
1407             HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);
1408             SmsTracker tracker = getSmsTracker(callingPackage, map, sentIntent, deliveryIntent,
1409                     getFormat(), null /*messageUri*/, false /*expectMore*/,
1410                     null /*fullMessageText*/, false /*isText*/,
1411                     true /*persistMessage*/, isForVvm, 0L /* messageId */, messageRef);
1412 
1413             if (!sendSmsByCarrierApp(true /* isDataSms */, tracker)) {
1414                 sendSubmitPdu(tracker);
1415             }
1416         } else {
1417             Rlog.e(TAG, "SMSDispatcher.sendData(): getSubmitPdu() returned null");
1418             triggerSentIntentForFailure(sentIntent);
1419         }
1420     }
1421 
1422     /**
1423      * Send a text based SMS.
1424      *
1425      * @param destAddr the address to send the message to
1426      * @param scAddr is the service center address or null to use
1427      *  the current default SMSC
1428      * @param text the body of the message to send
1429      * @param sentIntent if not NULL this <code>PendingIntent</code> is
1430      *  broadcast when the message is successfully sent, or failed.
1431      *  The result code will be <code>Activity.RESULT_OK<code> for success,
1432      *  or one of these errors:<br>
1433      *  <code>SmsManager.RESULT_ERROR_GENERIC_FAILURE</code><br>
1434      *  <code>SmsManager.RESULT_ERROR_RADIO_OFF</code><br>
1435      *  <code>SmsManager.RESULT_ERROR_NULL_PDU</code><br>
1436      *  <code>SmsManager.RESULT_ERROR_NO_SERVICE</code><br>
1437      *  <code>SmsManager.RESULT_ERROR_LIMIT_EXCEEDED</code><br>
1438      *  <code>SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE</code><br>
1439      *  <code>SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br>
1440      *  <code>SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br>
1441      *  <code>SmsManager.RESULT_RADIO_NOT_AVAILABLE</code><br>
1442      *  <code>SmsManager.RESULT_NETWORK_REJECT</code><br>
1443      *  <code>SmsManager.RESULT_INVALID_ARGUMENTS</code><br>
1444      *  <code>SmsManager.RESULT_INVALID_STATE</code><br>
1445      *  <code>SmsManager.RESULT_NO_MEMORY</code><br>
1446      *  <code>SmsManager.RESULT_INVALID_SMS_FORMAT</code><br>
1447      *  <code>SmsManager.RESULT_SYSTEM_ERROR</code><br>
1448      *  <code>SmsManager.RESULT_MODEM_ERROR</code><br>
1449      *  <code>SmsManager.RESULT_NETWORK_ERROR</code><br>
1450      *  <code>SmsManager.RESULT_ENCODING_ERROR</code><br>
1451      *  <code>SmsManager.RESULT_INVALID_SMSC_ADDRESS</code><br>
1452      *  <code>SmsManager.RESULT_OPERATION_NOT_ALLOWED</code><br>
1453      *  <code>SmsManager.RESULT_INTERNAL_ERROR</code><br>
1454      *  <code>SmsManager.RESULT_NO_RESOURCES</code><br>
1455      *  <code>SmsManager.RESULT_CANCELLED</code><br>
1456      *  <code>SmsManager.RESULT_REQUEST_NOT_SUPPORTED</code><br>
1457      *  <code>SmsManager.RESULT_NO_BLUETOOTH_SERVICE</code><br>
1458      *  <code>SmsManager.RESULT_INVALID_BLUETOOTH_ADDRESS</code><br>
1459      *  <code>SmsManager.RESULT_BLUETOOTH_DISCONNECTED</code><br>
1460      *  <code>SmsManager.RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br>
1461      *  <code>SmsManager.RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br>
1462      *  <code>SmsManager.RESULT_SMS_SEND_RETRY_FAILED</code><br>
1463      *  <code>SmsManager.RESULT_REMOTE_EXCEPTION</code><br>
1464      *  <code>SmsManager.RESULT_NO_DEFAULT_SMS_APP</code><br>
1465      *  <code>SmsManager.RESULT_RIL_RADIO_NOT_AVAILABLE</code><br>
1466      *  <code>SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br>
1467      *  <code>SmsManager.RESULT_RIL_NETWORK_REJECT</code><br>
1468      *  <code>SmsManager.RESULT_RIL_INVALID_STATE</code><br>
1469      *  <code>SmsManager.RESULT_RIL_INVALID_ARGUMENTS</code><br>
1470      *  <code>SmsManager.RESULT_RIL_NO_MEMORY</code><br>
1471      *  <code>SmsManager.RESULT_RIL_REQUEST_RATE_LIMITED</code><br>
1472      *  <code>SmsManager.RESULT_RIL_INVALID_SMS_FORMAT</code><br>
1473      *  <code>SmsManager.RESULT_RIL_SYSTEM_ERR</code><br>
1474      *  <code>SmsManager.RESULT_RIL_ENCODING_ERR</code><br>
1475      *  <code>SmsManager.RESULT_RIL_INVALID_SMSC_ADDRESS</code><br>
1476      *  <code>SmsManager.RESULT_RIL_MODEM_ERR</code><br>
1477      *  <code>SmsManager.RESULT_RIL_NETWORK_ERR</code><br>
1478      *  <code>SmsManager.RESULT_RIL_INTERNAL_ERR</code><br>
1479      *  <code>SmsManager.RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br>
1480      *  <code>SmsManager.RESULT_RIL_INVALID_MODEM_STATE</code><br>
1481      *  <code>SmsManager.RESULT_RIL_NETWORK_NOT_READY</code><br>
1482      *  <code>SmsManager.RESULT_RIL_OPERATION_NOT_ALLOWED</code><br>
1483      *  <code>SmsManager.RESULT_RIL_NO_RESOURCES</code><br>
1484      *  <code>SmsManager.RESULT_RIL_CANCELLED</code><br>
1485      *  <code>SmsManager.RESULT_RIL_SIM_ABSENT</code><br>
1486      *  <code>SmsManager.RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED</code><br>
1487      *  <code>SmsManager.RESULT_RIL_ACCESS_BARRED</code><br>
1488      *  <code>SmsManager.RESULT_RIL_BLOCKED_DUE_TO_CALL</code><br>
1489      *  For <code>SmsManager.RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors,
1490      *  the sentIntent may include the extra "errorCode" containing a radio technology specific
1491      *  value, generally only useful for troubleshooting.<br>
1492      *  The per-application based SMS control checks sentIntent. If sentIntent
1493      *  is NULL the caller will be checked against all unknown applications,
1494      *  which cause smaller number of SMS to be sent in checking period.
1495      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
1496      *  broadcast when the message is delivered to the recipient.  The
1497      * @param messageUri optional URI of the message if it is already stored in the system
1498      * @param callingPkg the calling package name
1499      * @param persistMessage whether to save the sent message into SMS DB for a
1500      *  non-default SMS app.
1501      *
1502      * @param priority Priority level of the message
1503      *  Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
1504      *  ---------------------------------
1505      *  PRIORITY      | Level of Priority
1506      *  ---------------------------------
1507      *      '00'      |     Normal
1508      *      '01'      |     Interactive
1509      *      '10'      |     Urgent
1510      *      '11'      |     Emergency
1511      *  ----------------------------------
1512      *  Any Other values included Negative considered as Invalid Priority Indicator of the message.
1513      * @param expectMore is a boolean to indicate the sending messages through same link or not.
1514      * @param validityPeriod Validity Period of the message in mins.
1515      *  Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
1516      *  Validity Period(Minimum) -> 5 mins
1517      *  Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
1518      *  Any Other values included Negative considered as Invalid Validity Period of the message.
1519      * @param messageId An id that uniquely identifies the message requested to be sent.
1520      *                 Used for logging and diagnostics purposes. The id may be NULL.
1521      */
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, long messageId)1522     public void sendText(String destAddr, String scAddr, String text,
1523             PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri,
1524             String callingPkg, boolean persistMessage, int priority,
1525             boolean expectMore, int validityPeriod, boolean isForVvm,
1526             long messageId) {
1527         sendText(destAddr, scAddr, text, sentIntent, deliveryIntent, messageUri, callingPkg,
1528                 persistMessage, priority, expectMore, validityPeriod, isForVvm, messageId, false);
1529     }
1530 
1531     /**
1532      * Send a text based SMS.
1533      *
1534      * @param destAddr the address to send the message to
1535      * @param scAddr is the service center address or null to use
1536      *  the current default SMSC
1537      * @param text the body of the message to send
1538      * @param sentIntent if not NULL this <code>PendingIntent</code> is
1539      *  broadcast when the message is successfully sent, or failed.
1540      *  The result code will be <code>Activity.RESULT_OK<code> for success,
1541      *  or one of these errors:<br>
1542      *  <code>SmsManager.RESULT_ERROR_GENERIC_FAILURE</code><br>
1543      *  <code>SmsManager.RESULT_ERROR_RADIO_OFF</code><br>
1544      *  <code>SmsManager.RESULT_ERROR_NULL_PDU</code><br>
1545      *  <code>SmsManager.RESULT_ERROR_NO_SERVICE</code><br>
1546      *  <code>SmsManager.RESULT_ERROR_LIMIT_EXCEEDED</code><br>
1547      *  <code>SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE</code><br>
1548      *  <code>SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br>
1549      *  <code>SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br>
1550      *  <code>SmsManager.RESULT_RADIO_NOT_AVAILABLE</code><br>
1551      *  <code>SmsManager.RESULT_NETWORK_REJECT</code><br>
1552      *  <code>SmsManager.RESULT_INVALID_ARGUMENTS</code><br>
1553      *  <code>SmsManager.RESULT_INVALID_STATE</code><br>
1554      *  <code>SmsManager.RESULT_NO_MEMORY</code><br>
1555      *  <code>SmsManager.RESULT_INVALID_SMS_FORMAT</code><br>
1556      *  <code>SmsManager.RESULT_SYSTEM_ERROR</code><br>
1557      *  <code>SmsManager.RESULT_MODEM_ERROR</code><br>
1558      *  <code>SmsManager.RESULT_NETWORK_ERROR</code><br>
1559      *  <code>SmsManager.RESULT_ENCODING_ERROR</code><br>
1560      *  <code>SmsManager.RESULT_INVALID_SMSC_ADDRESS</code><br>
1561      *  <code>SmsManager.RESULT_OPERATION_NOT_ALLOWED</code><br>
1562      *  <code>SmsManager.RESULT_INTERNAL_ERROR</code><br>
1563      *  <code>SmsManager.RESULT_NO_RESOURCES</code><br>
1564      *  <code>SmsManager.RESULT_CANCELLED</code><br>
1565      *  <code>SmsManager.RESULT_REQUEST_NOT_SUPPORTED</code><br>
1566      *  <code>SmsManager.RESULT_NO_BLUETOOTH_SERVICE</code><br>
1567      *  <code>SmsManager.RESULT_INVALID_BLUETOOTH_ADDRESS</code><br>
1568      *  <code>SmsManager.RESULT_BLUETOOTH_DISCONNECTED</code><br>
1569      *  <code>SmsManager.RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br>
1570      *  <code>SmsManager.RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br>
1571      *  <code>SmsManager.RESULT_SMS_SEND_RETRY_FAILED</code><br>
1572      *  <code>SmsManager.RESULT_REMOTE_EXCEPTION</code><br>
1573      *  <code>SmsManager.RESULT_NO_DEFAULT_SMS_APP</code><br>
1574      *  <code>SmsManager.RESULT_RIL_RADIO_NOT_AVAILABLE</code><br>
1575      *  <code>SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br>
1576      *  <code>SmsManager.RESULT_RIL_NETWORK_REJECT</code><br>
1577      *  <code>SmsManager.RESULT_RIL_INVALID_STATE</code><br>
1578      *  <code>SmsManager.RESULT_RIL_INVALID_ARGUMENTS</code><br>
1579      *  <code>SmsManager.RESULT_RIL_NO_MEMORY</code><br>
1580      *  <code>SmsManager.RESULT_RIL_REQUEST_RATE_LIMITED</code><br>
1581      *  <code>SmsManager.RESULT_RIL_INVALID_SMS_FORMAT</code><br>
1582      *  <code>SmsManager.RESULT_RIL_SYSTEM_ERR</code><br>
1583      *  <code>SmsManager.RESULT_RIL_ENCODING_ERR</code><br>
1584      *  <code>SmsManager.RESULT_RIL_INVALID_SMSC_ADDRESS</code><br>
1585      *  <code>SmsManager.RESULT_RIL_MODEM_ERR</code><br>
1586      *  <code>SmsManager.RESULT_RIL_NETWORK_ERR</code><br>
1587      *  <code>SmsManager.RESULT_RIL_INTERNAL_ERR</code><br>
1588      *  <code>SmsManager.RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br>
1589      *  <code>SmsManager.RESULT_RIL_INVALID_MODEM_STATE</code><br>
1590      *  <code>SmsManager.RESULT_RIL_NETWORK_NOT_READY</code><br>
1591      *  <code>SmsManager.RESULT_RIL_OPERATION_NOT_ALLOWED</code><br>
1592      *  <code>SmsManager.RESULT_RIL_NO_RESOURCES</code><br>
1593      *  <code>SmsManager.RESULT_RIL_CANCELLED</code><br>
1594      *  <code>SmsManager.RESULT_RIL_SIM_ABSENT</code><br>
1595      *  <code>SmsManager.RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED</code><br>
1596      *  <code>SmsManager.RESULT_RIL_ACCESS_BARRED</code><br>
1597      *  <code>SmsManager.RESULT_RIL_BLOCKED_DUE_TO_CALL</code><br>
1598      *  For <code>SmsManager.RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors,
1599      *  the sentIntent may include the extra "errorCode" containing a radio technology specific
1600      *  value, generally only useful for troubleshooting.<br>
1601      *  The per-application based SMS control checks sentIntent. If sentIntent
1602      *  is NULL the caller will be checked against all unknown applications,
1603      *  which cause smaller number of SMS to be sent in checking period.
1604      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
1605      *  broadcast when the message is delivered to the recipient.  The
1606      * @param messageUri optional URI of the message if it is already stored in the system
1607      * @param callingPkg the calling package name
1608      * @param persistMessage whether to save the sent message into SMS DB for a
1609      *  non-default SMS app.
1610      *
1611      * @param priority Priority level of the message
1612      *  Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
1613      *  ---------------------------------
1614      *  PRIORITY      | Level of Priority
1615      *  ---------------------------------
1616      *      '00'      |     Normal
1617      *      '01'      |     Interactive
1618      *      '10'      |     Urgent
1619      *      '11'      |     Emergency
1620      *  ----------------------------------
1621      *  Any Other values included Negative considered as Invalid Priority Indicator of the message.
1622      * @param expectMore is a boolean to indicate the sending messages through same link or not.
1623      * @param validityPeriod Validity Period of the message in mins.
1624      *  Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
1625      *  Validity Period(Minimum) -> 5 mins
1626      *  Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
1627      *  Any Other values included Negative considered as Invalid Validity Period of the message.
1628      * @param messageId An id that uniquely identifies the message requested to be sent.
1629      *                 Used for logging and diagnostics purposes. The id may be NULL.
1630      * @param skipShortCodeCheck Skip check for short code type destination address.
1631      */
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, long messageId, boolean skipShortCodeCheck)1632     public void sendText(String destAddr, String scAddr, String text,
1633                          PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri,
1634                          String callingPkg, boolean persistMessage, int priority,
1635                          boolean expectMore, int validityPeriod, boolean isForVvm,
1636                          long messageId, boolean skipShortCodeCheck) {
1637         Rlog.d(TAG, "sendText id: " + SmsController.formatCrossStackMessageId(messageId));
1638         int messageRef = nextMessageRef();
1639         SmsMessageBase.SubmitPduBase pdu = getSubmitPdu(
1640                 scAddr, destAddr, text, (deliveryIntent != null), null, priority, validityPeriod,
1641                 messageRef);
1642         if (pdu != null) {
1643             HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
1644             SmsTracker tracker = getSmsTracker(callingPkg, map, sentIntent, deliveryIntent,
1645                     getFormat(), messageUri, expectMore, text, true /*isText*/,
1646                     persistMessage, priority, validityPeriod, isForVvm, messageId, messageRef,
1647                     skipShortCodeCheck);
1648 
1649             if (!sendSmsByCarrierApp(false /* isDataSms */, tracker)) {
1650                 sendSubmitPdu(tracker);
1651             }
1652         } else {
1653             Rlog.e(TAG, "SmsDispatcher.sendText(): getSubmitPdu() returned null "
1654                     + SmsController.formatCrossStackMessageId(messageId));
1655             triggerSentIntentForFailure(sentIntent);
1656         }
1657     }
1658 
triggerSentIntentForFailure(PendingIntent sentIntent)1659     private void triggerSentIntentForFailure(PendingIntent sentIntent) {
1660         if (sentIntent != null) {
1661             try {
1662                 sentIntent.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE);
1663             } catch (CanceledException ex) {
1664                 Rlog.e(TAG, "Intent has been canceled!");
1665             }
1666         }
1667     }
1668 
triggerSentIntentForFailure(List<PendingIntent> sentIntents)1669     private void triggerSentIntentForFailure(List<PendingIntent> sentIntents) {
1670         if (sentIntents == null) {
1671             return;
1672         }
1673 
1674         for (PendingIntent sentIntent : sentIntents) {
1675             triggerSentIntentForFailure(sentIntent);
1676         }
1677     }
1678 
sendSmsByCarrierApp(boolean isDataSms, SmsTracker tracker )1679     private boolean sendSmsByCarrierApp(boolean isDataSms, SmsTracker tracker ) {
1680         String carrierPackage = getCarrierAppPackageName();
1681         if (carrierPackage != null) {
1682             Rlog.d(TAG, "Found carrier package " + carrierPackage);
1683             SmsSender smsSender;
1684             if (isDataSms) {
1685                 smsSender = new DataSmsSender(tracker);
1686             } else {
1687                 smsSender = new TextSmsSender(tracker);
1688             }
1689             smsSender.sendSmsByCarrierApp(carrierPackage, new SmsSenderCallback(smsSender));
1690             return true;
1691         }
1692 
1693         return false;
1694     }
1695 
getSubmitPdu(String scAddr, String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader, int priority, int validityPeriod)1696     protected abstract SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
1697             String message, boolean statusReportRequested, SmsHeader smsHeader,
1698             int priority, int validityPeriod);
1699 
getSubmitPdu(String scAddr, String destAddr, int destPort, byte[] message, boolean statusReportRequested)1700     protected abstract SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
1701             int destPort, byte[] message, boolean statusReportRequested);
1702 
getSubmitPdu(String scAddr, String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader, int priority, int validityPeriod, int messageRef)1703     protected abstract SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
1704             String message, boolean statusReportRequested, SmsHeader smsHeader,
1705             int priority, int validityPeriod, int messageRef);
1706 
1707 
getSubmitPdu(String scAddr, String destAddr, int destPort, byte[] message, boolean statusReportRequested, int messageRef)1708     protected abstract SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
1709             int destPort, byte[] message, boolean statusReportRequested, int messageRef);
1710 
1711     /**
1712      * Calculate the number of septets needed to encode the message. This function should only be
1713      * called for individual segments of multipart message.
1714      *
1715      * @param messageBody the message to encode
1716      * @param use7bitOnly ignore (but still count) illegal characters if true
1717      * @return TextEncodingDetails
1718      */
1719     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
calculateLength(CharSequence messageBody, boolean use7bitOnly)1720     protected abstract TextEncodingDetails calculateLength(CharSequence messageBody,
1721             boolean use7bitOnly);
1722 
1723     /**
1724      * Send a multi-part text based SMS.
1725      *
1726      * @param destAddr the address to send the message to
1727      * @param scAddr is the service center address or null to use
1728      *  the current default SMSC
1729      * @param parts an <code>ArrayList</code> of strings that, in order,
1730      *  comprise the original message
1731      * @param sentIntents if not null, an <code>ArrayList</code> of
1732      *  <code>PendingIntent</code>s (one for each message part) that is
1733      *  broadcast when the corresponding message part has been sent.
1734      *  The result code will be <code>Activity.RESULT_OK<code> for success,
1735      *  or one of these errors:
1736      *  <code>SmsManager.RESULT_ERROR_GENERIC_FAILURE</code><br>
1737      *  <code>SmsManager.RESULT_ERROR_RADIO_OFF</code><br>
1738      *  <code>SmsManager.RESULT_ERROR_NULL_PDU</code><br>
1739      *  <code>SmsManager.RESULT_ERROR_NO_SERVICE</code><br>
1740      *  <code>SmsManager.RESULT_ERROR_LIMIT_EXCEEDED</code><br>
1741      *  <code>SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE</code><br>
1742      *  <code>SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br>
1743      *  <code>SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br>
1744      *  <code>SmsManager.RESULT_RADIO_NOT_AVAILABLE</code><br>
1745      *  <code>SmsManager.RESULT_NETWORK_REJECT</code><br>
1746      *  <code>SmsManager.RESULT_INVALID_ARGUMENTS</code><br>
1747      *  <code>SmsManager.RESULT_INVALID_STATE</code><br>
1748      *  <code>SmsManager.RESULT_NO_MEMORY</code><br>
1749      *  <code>SmsManager.RESULT_INVALID_SMS_FORMAT</code><br>
1750      *  <code>SmsManager.RESULT_SYSTEM_ERROR</code><br>
1751      *  <code>SmsManager.RESULT_MODEM_ERROR</code><br>
1752      *  <code>SmsManager.RESULT_NETWORK_ERROR</code><br>
1753      *  <code>SmsManager.RESULT_ENCODING_ERROR</code><br>
1754      *  <code>SmsManager.RESULT_INVALID_SMSC_ADDRESS</code><br>
1755      *  <code>SmsManager.RESULT_OPERATION_NOT_ALLOWED</code><br>
1756      *  <code>SmsManager.RESULT_INTERNAL_ERROR</code><br>
1757      *  <code>SmsManager.RESULT_NO_RESOURCES</code><br>
1758      *  <code>SmsManager.RESULT_CANCELLED</code><br>
1759      *  <code>SmsManager.RESULT_REQUEST_NOT_SUPPORTED</code><br>
1760      *  <code>SmsManager.RESULT_NO_BLUETOOTH_SERVICE</code><br>
1761      *  <code>SmsManager.RESULT_INVALID_BLUETOOTH_ADDRESS</code><br>
1762      *  <code>SmsManager.RESULT_BLUETOOTH_DISCONNECTED</code><br>
1763      *  <code>SmsManager.RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br>
1764      *  <code>SmsManager.RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br>
1765      *  <code>SmsManager.RESULT_SMS_SEND_RETRY_FAILED</code><br>
1766      *  <code>SmsManager.RESULT_REMOTE_EXCEPTION</code><br>
1767      *  <code>SmsManager.RESULT_NO_DEFAULT_SMS_APP</code><br>
1768      *  <code>SmsManager.RESULT_RIL_RADIO_NOT_AVAILABLE</code><br>
1769      *  <code>SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br>
1770      *  <code>SmsManager.RESULT_RIL_NETWORK_REJECT</code><br>
1771      *  <code>SmsManager.RESULT_RIL_INVALID_STATE</code><br>
1772      *  <code>SmsManager.RESULT_RIL_INVALID_ARGUMENTS</code><br>
1773      *  <code>SmsManager.RESULT_RIL_NO_MEMORY</code><br>
1774      *  <code>SmsManager.RESULT_RIL_REQUEST_RATE_LIMITED</code><br>
1775      *  <code>SmsManager.RESULT_RIL_INVALID_SMS_FORMAT</code><br>
1776      *  <code>SmsManager.RESULT_RIL_SYSTEM_ERR</code><br>
1777      *  <code>SmsManager.RESULT_RIL_ENCODING_ERR</code><br>
1778      *  <code>SmsManager.RESULT_RIL_INVALID_SMSC_ADDRESS</code><br>
1779      *  <code>SmsManager.RESULT_RIL_MODEM_ERR</code><br>
1780      *  <code>SmsManager.RESULT_RIL_NETWORK_ERR</code><br>
1781      *  <code>SmsManager.RESULT_RIL_INTERNAL_ERR</code><br>
1782      *  <code>SmsManager.RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br>
1783      *  <code>SmsManager.RESULT_RIL_INVALID_MODEM_STATE</code><br>
1784      *  <code>SmsManager.RESULT_RIL_NETWORK_NOT_READY</code><br>
1785      *  <code>SmsManager.RESULT_RIL_OPERATION_NOT_ALLOWED</code><br>
1786      *  <code>SmsManager.RESULT_RIL_NO_RESOURCES</code><br>
1787      *  <code>SmsManager.RESULT_RIL_CANCELLED</code><br>
1788      *  <code>SmsManager.RESULT_RIL_SIM_ABSENT</code><br>
1789      *  <code>SmsManager.RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED</code><br>
1790      *  <code>SmsManager.RESULT_RIL_ACCESS_BARRED</code><br>
1791      *  <code>SmsManager.RESULT_RIL_BLOCKED_DUE_TO_CALL</code><br>
1792      *  For <code>SmsManager.RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors,
1793      *  the sentIntent may include the extra "errorCode" containing a radio technology specific
1794      *  value, generally only useful for troubleshooting.<br>
1795      *  The per-application based SMS control checks sentIntent. If sentIntent
1796      *  is NULL the caller will be checked against all unknown applications,
1797      *  which cause smaller number of SMS to be sent in checking period.
1798      * @param deliveryIntents if not null, an <code>ArrayList</code> of
1799      *  <code>PendingIntent</code>s (one for each message part) that is
1800      *  broadcast when the corresponding message part has been delivered
1801      *  to the recipient.  The raw pdu of the status report is in the
1802      * @param messageUri optional URI of the message if it is already stored in the system
1803      * @param callingPkg the calling package name
1804      * @param persistMessage whether to save the sent message into SMS DB for a
1805      *   non-default SMS app.
1806      * @param priority Priority level of the message
1807      *  Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
1808      *  ---------------------------------
1809      *  PRIORITY      | Level of Priority
1810      *  ---------------------------------
1811      *      '00'      |     Normal
1812      *      '01'      |     Interactive
1813      *      '10'      |     Urgent
1814      *      '11'      |     Emergency
1815      *  ----------------------------------
1816      *  Any Other values included Negative considered as Invalid Priority Indicator of the message.
1817      * @param expectMore is a boolean to indicate the sending messages through same link or not.
1818      * @param validityPeriod Validity Period of the message in mins.
1819      *  Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
1820      *  Validity Period(Minimum) -> 5 mins
1821      *  Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
1822      *  Any Other values included Negative considered as Invalid Validity Period of the message.
1823      */
1824     @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, long messageId)1825     public void sendMultipartText(String destAddr, String scAddr,
1826             ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
1827             ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg,
1828             boolean persistMessage, int priority, boolean expectMore, int validityPeriod,
1829             long messageId) {
1830         final String fullMessageText = getMultipartMessageText(parts);
1831         int refNumber = getNextConcatenatedRef() & 0x00FF;
1832         int encoding = SmsConstants.ENCODING_UNKNOWN;
1833         int msgCount = parts.size();
1834         if (msgCount < 1) {
1835             triggerSentIntentForFailure(sentIntents);
1836             return;
1837         }
1838 
1839         TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount];
1840         for (int i = 0; i < msgCount; i++) {
1841             TextEncodingDetails details = calculateLength(parts.get(i), false);
1842             if (encoding != details.codeUnitSize
1843                     && (encoding == SmsConstants.ENCODING_UNKNOWN
1844                             || encoding == SmsConstants.ENCODING_7BIT)) {
1845                 encoding = details.codeUnitSize;
1846             }
1847             encodingForParts[i] = details;
1848         }
1849 
1850         SmsTracker[] trackers = new SmsTracker[msgCount];
1851 
1852         // States to track at the message level (for all parts)
1853         final AtomicInteger unsentPartCount = new AtomicInteger(msgCount);
1854         final AtomicBoolean anyPartFailed = new AtomicBoolean(false);
1855 
1856         for (int i = 0; i < msgCount; i++) {
1857             SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
1858             concatRef.refNumber = refNumber;
1859             concatRef.seqNumber = i + 1;  // 1-based sequence
1860             concatRef.msgCount = msgCount;
1861             // TODO: We currently set this to true since our messaging app will never
1862             // send more than 255 parts (it converts the message to MMS well before that).
1863             // However, we should support 3rd party messaging apps that might need 16-bit
1864             // references
1865             // Note:  It's not sufficient to just flip this bit to true; it will have
1866             // ripple effects (several calculations assume 8-bit ref).
1867             concatRef.isEightBits = true;
1868             SmsHeader smsHeader = new SmsHeader();
1869             smsHeader.concatRef = concatRef;
1870 
1871             // Set the national language tables for 3GPP 7-bit encoding, if enabled.
1872             if (encoding == SmsConstants.ENCODING_7BIT) {
1873                 smsHeader.languageTable = encodingForParts[i].languageTable;
1874                 smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable;
1875             }
1876 
1877             PendingIntent sentIntent = null;
1878             if (sentIntents != null && sentIntents.size() > i) {
1879                 sentIntent = sentIntents.get(i);
1880             }
1881 
1882             PendingIntent deliveryIntent = null;
1883             if (deliveryIntents != null && deliveryIntents.size() > i) {
1884                 deliveryIntent = deliveryIntents.get(i);
1885             }
1886             int messageRef = nextMessageRef();
1887             trackers[i] =
1888                 getNewSubmitPduTracker(callingPkg, destAddr, scAddr, parts.get(i), smsHeader,
1889                         encoding, sentIntent, deliveryIntent, (i == (msgCount - 1)),
1890                         unsentPartCount, anyPartFailed, messageUri,
1891                         fullMessageText, priority, expectMore, validityPeriod, messageId,
1892                         messageRef);
1893             if (trackers[i] == null) {
1894                 triggerSentIntentForFailure(sentIntents);
1895                 return;
1896             }
1897             trackers[i].mPersistMessage = persistMessage;
1898         }
1899 
1900         String carrierPackage = getCarrierAppPackageName();
1901         if (carrierPackage != null) {
1902             Rlog.d(TAG, "Found carrier package " + carrierPackage + " "
1903                     + SmsController.formatCrossStackMessageId(getMultiTrackermessageId(trackers)));
1904             MultipartSmsSender smsSender = new MultipartSmsSender(parts, trackers);
1905             smsSender.sendSmsByCarrierApp(carrierPackage, new SmsSenderCallback(smsSender));
1906         } else {
1907             Rlog.v(TAG, "No carrier package. "
1908                     + SmsController.formatCrossStackMessageId(getMultiTrackermessageId(trackers)));
1909             sendSubmitPdu(trackers);
1910         }
1911     }
1912 
getMultiTrackermessageId(SmsTracker[] trackers)1913     private long getMultiTrackermessageId(SmsTracker[] trackers) {
1914         if (trackers.length == 0) {
1915             return 0L;
1916         }
1917         return trackers[0].mMessageId;
1918     }
1919 
1920     /**
1921      * Create a new SubmitPdu and return the SMS tracker.
1922      */
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, long messageId, int messageRef)1923     private SmsTracker getNewSubmitPduTracker(String callingPackage, String destinationAddress,
1924             String scAddress, String message, SmsHeader smsHeader, int encoding,
1925             PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart,
1926             AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
1927             String fullMessageText, int priority, boolean expectMore, int validityPeriod,
1928             long messageId, int messageRef) {
1929         if (isCdmaMo()) {
1930             UserData uData = new UserData();
1931             uData.payloadStr = message;
1932             uData.userDataHeader = smsHeader;
1933             if (encoding == SmsConstants.ENCODING_7BIT) {
1934                 uData.msgEncoding = isAscii7bitSupportedForLongMessage()
1935                         ? UserData.ENCODING_7BIT_ASCII : UserData.ENCODING_GSM_7BIT_ALPHABET;
1936                 Rlog.d(TAG, "Message encoding for proper 7 bit: " + uData.msgEncoding);
1937             } else { // assume UTF-16
1938                 uData.msgEncoding = UserData.ENCODING_UNICODE_16;
1939             }
1940             uData.msgEncodingSet = true;
1941 
1942             /* By setting the statusReportRequested bit only for the
1943              * last message fragment, this will result in only one
1944              * callback to the sender when that last fragment delivery
1945              * has been acknowledged. */
1946             //TODO FIX
1947             SmsMessageBase.SubmitPduBase submitPdu =
1948                     com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(destinationAddress,
1949                             uData, (deliveryIntent != null) && lastPart, priority);
1950 
1951             if (submitPdu != null) {
1952                 HashMap map = getSmsTrackerMap(destinationAddress, scAddress,
1953                         message, submitPdu);
1954                 return getSmsTracker(callingPackage, map, sentIntent, deliveryIntent,
1955                         getFormat(), unsentPartCount, anyPartFailed, messageUri, smsHeader,
1956                         (!lastPart || expectMore), fullMessageText, true /*isText*/,
1957                         true /*persistMessage*/, priority, validityPeriod, false /* isForVvm */,
1958                         messageId, messageRef, false);
1959             } else {
1960                 Rlog.e(TAG, "CdmaSMSDispatcher.getNewSubmitPduTracker(): getSubmitPdu() returned "
1961                         + "null " + SmsController.formatCrossStackMessageId(messageId));
1962                 return null;
1963             }
1964         } else {
1965             SmsMessageBase.SubmitPduBase pdu =
1966                     com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
1967                             destinationAddress, message, deliveryIntent != null,
1968                             SmsHeader.toByteArray(smsHeader), encoding, smsHeader.languageTable,
1969                             smsHeader.languageShiftTable, validityPeriod, messageRef);
1970             if (pdu != null) {
1971                 HashMap map = getSmsTrackerMap(destinationAddress, scAddress, message, pdu);
1972                 return getSmsTracker(callingPackage, map, sentIntent,
1973                         deliveryIntent, getFormat(), unsentPartCount, anyPartFailed, messageUri,
1974                         smsHeader, (!lastPart || expectMore), fullMessageText, true /*isText*/,
1975                         false /*persistMessage*/, priority, validityPeriod, false /* isForVvm */,
1976                         messageId, messageRef, false);
1977             } else {
1978                 Rlog.e(TAG, "GsmSMSDispatcher.getNewSubmitPduTracker(): getSubmitPdu() returned "
1979                         + "null " + SmsController.formatCrossStackMessageId(messageId));
1980                 return null;
1981             }
1982         }
1983     }
1984 
1985     /**
1986      * Send a single or a multi-part SMS
1987      *
1988      * @param trackers each tracker will contain:
1989      * -smsc the SMSC to send the message through, or NULL for the
1990      *  default SMSC
1991      * -pdu the raw PDU to send
1992      * -sentIntent if not NULL this <code>Intent</code> is
1993      *  broadcast when the message is successfully sent, or failed.
1994      *  The result code will be <code>Activity.RESULT_OK<code> for success,
1995      *  or one of these errors:
1996      *  <code>SmsManager.RESULT_ERROR_GENERIC_FAILURE</code><br>
1997      *  <code>SmsManager.RESULT_ERROR_RADIO_OFF</code><br>
1998      *  <code>SmsManager.RESULT_ERROR_NULL_PDU</code><br>
1999      *  <code>SmsManager.RESULT_ERROR_NO_SERVICE</code><br>
2000      *  <code>SmsManager.RESULT_ERROR_LIMIT_EXCEEDED</code><br>
2001      *  <code>SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE</code><br>
2002      *  <code>SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED</code><br>
2003      *  <code>SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED</code><br>
2004      *  <code>SmsManager.RESULT_RADIO_NOT_AVAILABLE</code><br>
2005      *  <code>SmsManager.RESULT_NETWORK_REJECT</code><br>
2006      *  <code>SmsManager.RESULT_INVALID_ARGUMENTS</code><br>
2007      *  <code>SmsManager.RESULT_INVALID_STATE</code><br>
2008      *  <code>SmsManager.RESULT_NO_MEMORY</code><br>
2009      *  <code>SmsManager.RESULT_INVALID_SMS_FORMAT</code><br>
2010      *  <code>SmsManager.RESULT_SYSTEM_ERROR</code><br>
2011      *  <code>SmsManager.RESULT_MODEM_ERROR</code><br>
2012      *  <code>SmsManager.RESULT_NETWORK_ERROR</code><br>
2013      *  <code>SmsManager.RESULT_ENCODING_ERROR</code><br>
2014      *  <code>SmsManager.RESULT_INVALID_SMSC_ADDRESS</code><br>
2015      *  <code>SmsManager.RESULT_OPERATION_NOT_ALLOWED</code><br>
2016      *  <code>SmsManager.RESULT_INTERNAL_ERROR</code><br>
2017      *  <code>SmsManager.RESULT_NO_RESOURCES</code><br>
2018      *  <code>SmsManager.RESULT_CANCELLED</code><br>
2019      *  <code>SmsManager.RESULT_REQUEST_NOT_SUPPORTED</code><br>
2020      *  <code>SmsManager.RESULT_NO_BLUETOOTH_SERVICE</code><br>
2021      *  <code>SmsManager.RESULT_INVALID_BLUETOOTH_ADDRESS</code><br>
2022      *  <code>SmsManager.RESULT_BLUETOOTH_DISCONNECTED</code><br>
2023      *  <code>SmsManager.RESULT_UNEXPECTED_EVENT_STOP_SENDING</code><br>
2024      *  <code>SmsManager.RESULT_SMS_BLOCKED_DURING_EMERGENCY</code><br>
2025      *  <code>SmsManager.RESULT_SMS_SEND_RETRY_FAILED</code><br>
2026      *  <code>SmsManager.RESULT_REMOTE_EXCEPTION</code><br>
2027      *  <code>SmsManager.RESULT_NO_DEFAULT_SMS_APP</code><br>
2028      *  <code>SmsManager.RESULT_RIL_RADIO_NOT_AVAILABLE</code><br>
2029      *  <code>SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY</code><br>
2030      *  <code>SmsManager.RESULT_RIL_NETWORK_REJECT</code><br>
2031      *  <code>SmsManager.RESULT_RIL_INVALID_STATE</code><br>
2032      *  <code>SmsManager.RESULT_RIL_INVALID_ARGUMENTS</code><br>
2033      *  <code>SmsManager.RESULT_RIL_NO_MEMORY</code><br>
2034      *  <code>SmsManager.RESULT_RIL_REQUEST_RATE_LIMITED</code><br>
2035      *  <code>SmsManager.RESULT_RIL_INVALID_SMS_FORMAT</code><br>
2036      *  <code>SmsManager.RESULT_RIL_SYSTEM_ERR</code><br>
2037      *  <code>SmsManager.RESULT_RIL_ENCODING_ERR</code><br>
2038      *  <code>SmsManager.RESULT_RIL_INVALID_SMSC_ADDRESS</code><br>
2039      *  <code>SmsManager.RESULT_RIL_MODEM_ERR</code><br>
2040      *  <code>SmsManager.RESULT_RIL_NETWORK_ERR</code><br>
2041      *  <code>SmsManager.RESULT_RIL_INTERNAL_ERR</code><br>
2042      *  <code>SmsManager.RESULT_RIL_REQUEST_NOT_SUPPORTED</code><br>
2043      *  <code>SmsManager.RESULT_RIL_INVALID_MODEM_STATE</code><br>
2044      *  <code>SmsManager.RESULT_RIL_NETWORK_NOT_READY</code><br>
2045      *  <code>SmsManager.RESULT_RIL_OPERATION_NOT_ALLOWED</code><br>
2046      *  <code>SmsManager.RESULT_RIL_NO_RESOURCES</code><br>
2047      *  <code>SmsManager.RESULT_RIL_CANCELLED</code><br>
2048      *  <code>SmsManager.RESULT_RIL_SIM_ABSENT</code><br>
2049      *  <code>SmsManager.RESULT_RIL_SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED</code><br>
2050      *  <code>SmsManager.RESULT_RIL_ACCESS_BARRED</code><br>
2051      *  <code>SmsManager.RESULT_RIL_BLOCKED_DUE_TO_CALL</code><br>
2052      *  For <code>SmsManager.RESULT_ERROR_GENERIC_FAILURE</code> or any of the RESULT_RIL errors,
2053      *  the sentIntent may include the extra "errorCode" containing a radio technology specific
2054      *  value, generally only useful for troubleshooting.<br>
2055      *  The per-application based SMS control checks sentIntent. If sentIntent
2056      *  is NULL the caller will be checked against all unknown applications,
2057      *  which cause smaller number of SMS to be sent in checking period.
2058      * -deliveryIntent if not NULL this <code>Intent</code> is
2059      *  broadcast when the message is delivered to the recipient.  The
2060      *  raw pdu of the status report is in the extended data ("pdu").
2061      * -param destAddr the destination phone number (for short code confirmation)
2062      */
2063     @VisibleForTesting
sendRawPdu(SmsTracker[] trackers)2064     public void sendRawPdu(SmsTracker[] trackers) {
2065         @SmsManager.Result int error = SmsManager.RESULT_ERROR_NONE;
2066         PackageInfo appInfo = null;
2067         if (mSmsSendDisabled) {
2068             Rlog.e(TAG, "Device does not support sending sms.");
2069             error = SmsManager.RESULT_ERROR_NO_SERVICE;
2070         } else {
2071             for (SmsTracker tracker : trackers) {
2072                 if (tracker.getData().get(MAP_KEY_PDU) == null) {
2073                     Rlog.e(TAG, "Empty PDU");
2074                     error = SmsManager.RESULT_ERROR_NULL_PDU;
2075                     break;
2076                 }
2077             }
2078 
2079             if (error == SmsManager.RESULT_ERROR_NONE) {
2080                 UserHandle userHandle = UserHandle.of(trackers[0].mUserId);
2081                 PackageManager pm = mContext.createContextAsUser(userHandle, 0).getPackageManager();
2082 
2083                 try {
2084                     // Get package info via packagemanager
2085                     appInfo =
2086                             pm.getPackageInfo(
2087                                     trackers[0].getAppPackageName(),
2088                                     PackageManager.GET_SIGNATURES);
2089                 } catch (PackageManager.NameNotFoundException e) {
2090                     Rlog.e(TAG, "Can't get calling app package info: refusing to send SMS "
2091                             + SmsController.formatCrossStackMessageId(
2092                                     getMultiTrackermessageId(trackers)));
2093                     error = SmsManager.RESULT_ERROR_GENERIC_FAILURE;
2094                 }
2095             }
2096         }
2097 
2098         if (error != SmsManager.RESULT_ERROR_NONE) {
2099             handleSmsTrackersFailure(trackers, error, NO_ERROR_CODE);
2100             return;
2101         }
2102 
2103         // checkDestination() returns true if the destination is not a premium short code or the
2104         // sending app is approved to send to short codes. Otherwise, a message is sent to our
2105         // handler with the SmsTracker to request user confirmation before sending.
2106         if (checkDestination(trackers)) {
2107             // check for excessive outgoing SMS usage by this app
2108             if (!mSmsDispatchersController
2109                     .getUsageMonitor()
2110                     .check(appInfo.packageName, trackers.length)) {
2111                 sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, trackers));
2112                 return;
2113             }
2114 
2115             for (SmsTracker tracker : trackers) {
2116                 sendSms(tracker);
2117             }
2118         }
2119 
2120         if (mTelephonyManager.isEmergencyNumber(trackers[0].mDestAddress)) {
2121             new AsyncEmergencyContactNotifier(mContext).execute();
2122         }
2123     }
2124 
2125     /**
2126      * Check if destination is a potential premium short code and sender is not pre-approved to send
2127      * to short codes.
2128      *
2129      * @param trackers the trackers for a single or a multi-part SMS to send
2130      * @return true if the destination is approved; false if user confirmation event was sent
2131      */
checkDestination(SmsTracker[] trackers)2132     boolean checkDestination(SmsTracker[] trackers) {
2133         if (mContext.checkCallingOrSelfPermission(SEND_SMS_NO_CONFIRMATION)
2134                 == PackageManager.PERMISSION_GRANTED || trackers[0].mIsForVvm
2135                 || trackers[0].mSkipShortCodeDestAddrCheck) {
2136             return true;            // app is pre-approved to send to short codes
2137         } else {
2138             int rule = mPremiumSmsRule.get();
2139             int smsCategory = SmsManager.SMS_CATEGORY_NOT_SHORT_CODE;
2140             if (rule == PREMIUM_RULE_USE_SIM || rule == PREMIUM_RULE_USE_BOTH) {
2141                 String simCountryIso =
2142                         mTelephonyManager.getSimCountryIsoForPhone(mPhone.getPhoneId());
2143                 if (simCountryIso == null || simCountryIso.length() != 2) {
2144                     Rlog.e(TAG, "Can't get SIM country Iso: trying network country Iso "
2145                             + SmsController.formatCrossStackMessageId(
2146                                     getMultiTrackermessageId(trackers)));
2147                     simCountryIso =
2148                             mTelephonyManager.getNetworkCountryIso(mPhone.getPhoneId());
2149                 }
2150 
2151                 smsCategory =
2152                         mSmsDispatchersController
2153                                 .getUsageMonitor()
2154                                 .checkDestination(trackers[0].mDestAddress, simCountryIso);
2155             }
2156             if (rule == PREMIUM_RULE_USE_NETWORK || rule == PREMIUM_RULE_USE_BOTH) {
2157                 String networkCountryIso =
2158                         mTelephonyManager.getNetworkCountryIso(mPhone.getPhoneId());
2159                 if (networkCountryIso == null || networkCountryIso.length() != 2) {
2160                     Rlog.e(TAG, "Can't get Network country Iso: trying SIM country Iso "
2161                             + SmsController.formatCrossStackMessageId(
2162                                     getMultiTrackermessageId(trackers)));
2163                     networkCountryIso =
2164                             mTelephonyManager.getSimCountryIsoForPhone(mPhone.getPhoneId());
2165                 }
2166 
2167                 smsCategory =
2168                         SmsUsageMonitor.mergeShortCodeCategories(
2169                                 smsCategory,
2170                                 mSmsDispatchersController
2171                                         .getUsageMonitor()
2172                                         .checkDestination(
2173                                                 trackers[0].mDestAddress, networkCountryIso));
2174             }
2175 
2176             if (smsCategory != SmsManager.SMS_CATEGORY_NOT_SHORT_CODE) {
2177                 int xmlVersion = mSmsDispatchersController.getUsageMonitor()
2178                         .getShortCodeXmlFileVersion();
2179                 mPhone.getSmsStats().onOutgoingShortCodeSms(smsCategory, xmlVersion);
2180             }
2181 
2182             if (smsCategory == SmsManager.SMS_CATEGORY_NOT_SHORT_CODE
2183                     || smsCategory == SmsManager.SMS_CATEGORY_FREE_SHORT_CODE
2184                     || smsCategory == SmsManager.SMS_CATEGORY_STANDARD_SHORT_CODE) {
2185                 return true;    // not a premium short code
2186             }
2187 
2188             // Do not allow any premium sms during SuW
2189             if (Settings.Global.getInt(mResolver, Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
2190                 Rlog.e(TAG, "Can't send premium sms during Setup Wizard "
2191                         + SmsController.formatCrossStackMessageId(
2192                                 getMultiTrackermessageId(trackers)));
2193                 return false;
2194             }
2195 
2196             // Wait for user confirmation unless the user has set permission to always allow/deny
2197             int premiumSmsPermission =
2198                     mSmsDispatchersController
2199                             .getUsageMonitor()
2200                             .getPremiumSmsPermission(trackers[0].getAppPackageName());
2201             if (premiumSmsPermission == SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) {
2202                 // First time trying to send to premium SMS.
2203                 premiumSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER;
2204             }
2205 
2206             switch (premiumSmsPermission) {
2207                 case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW:
2208                     Rlog.d(TAG, "User approved this app to send to premium SMS "
2209                             + SmsController.formatCrossStackMessageId(
2210                                     getMultiTrackermessageId(trackers)));
2211                     return true;
2212 
2213                 case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW:
2214                     Rlog.w(TAG, "User denied this app from sending to premium SMS "
2215                             + SmsController.formatCrossStackMessageId(
2216                                     getMultiTrackermessageId(trackers)));
2217                     Message msg = obtainMessage(EVENT_SENDING_NOT_ALLOWED, trackers);
2218                     sendMessage(msg);
2219                     return false;   // reject this message
2220 
2221                 case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER:
2222                 default:
2223                     int event;
2224                     if (smsCategory == SmsManager.SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE) {
2225                         event = EVENT_CONFIRM_SEND_TO_POSSIBLE_PREMIUM_SHORT_CODE;
2226                     } else {
2227                         event = EVENT_CONFIRM_SEND_TO_PREMIUM_SHORT_CODE;
2228                     }
2229                     sendMessage(obtainMessage(event, trackers));
2230                     return false;   // wait for user confirmation
2231             }
2232         }
2233     }
2234 
2235     /**
2236      * Deny sending a single or a multi-part SMS if the outgoing queue limit is reached. Used when
2237      * the message must be confirmed by the user due to excessive usage or potential premium SMS
2238      * detected.
2239      *
2240      * @param trackers the SmsTracker array for the message to send
2241      * @return true if the message was denied; false to continue with send confirmation
2242      */
denyIfQueueLimitReached(SmsTracker[] trackers)2243     private boolean denyIfQueueLimitReached(SmsTracker[] trackers) {
2244         // one SmsTracker array is treated as one message for checking queue limit.
2245         if (mPendingTrackerCount >= MO_MSG_QUEUE_LIMIT) {
2246             // Deny sending message when the queue limit is reached.
2247             Rlog.e(TAG, "Denied because queue limit reached "
2248                     + SmsController.formatCrossStackMessageId(getMultiTrackermessageId(trackers)));
2249             handleSmsTrackersFailure(
2250                     trackers, SmsManager.RESULT_ERROR_LIMIT_EXCEEDED, NO_ERROR_CODE);
2251             return true;
2252         }
2253         mPendingTrackerCount++;
2254         return false;
2255     }
2256 
2257     /**
2258      * Returns the label for the specified app package name.
2259      * @param appPackage the package name of the app requesting to send an SMS
2260      * @return the label for the specified app, or the package name if getApplicationInfo() fails
2261      */
getAppLabel(String appPackage, @UserIdInt int userId)2262     private CharSequence getAppLabel(String appPackage, @UserIdInt int userId) {
2263         PackageManager pm = mContext.getPackageManager();
2264         try {
2265             ApplicationInfo appInfo = pm.getApplicationInfoAsUser(appPackage, 0,
2266                     UserHandle.of(userId));
2267             return appInfo.loadSafeLabel(pm);
2268         } catch (PackageManager.NameNotFoundException e) {
2269             Rlog.e(TAG, "PackageManager Name Not Found for package " + appPackage);
2270             return appPackage;  // fall back to package name if we can't get app label
2271         }
2272     }
2273 
2274     /**
2275      * Post an alert when SMS needs confirmation due to excessive usage.
2276      *
2277      * @param trackers the SmsTracker array for the current message.
2278      */
handleReachSentLimit(SmsTracker[] trackers)2279     protected void handleReachSentLimit(SmsTracker[] trackers) {
2280         if (denyIfQueueLimitReached(trackers)) {
2281             return;     // queue limit reached; error was returned to caller
2282         }
2283 
2284         CharSequence appLabel = getAppLabel(trackers[0].getAppPackageName(), trackers[0].mUserId);
2285         Resources r = Resources.getSystem();
2286         Spanned messageText = Html.fromHtml(r.getString(R.string.sms_control_message, appLabel));
2287 
2288         // Construct ConfirmDialogListenter for Rate Limit handling
2289         ConfirmDialogListener listener =
2290                 new ConfirmDialogListener(trackers, null, ConfirmDialogListener.RATE_LIMIT);
2291 
2292         AlertDialog d = new AlertDialog.Builder(mContext)
2293                 .setTitle(R.string.sms_control_title)
2294                 .setIcon(R.drawable.stat_sys_warning)
2295                 .setMessage(messageText)
2296                 .setPositiveButton(r.getString(R.string.sms_control_yes), listener)
2297                 .setNegativeButton(r.getString(R.string.sms_control_no), listener)
2298                 .setOnCancelListener(listener)
2299                 .create();
2300 
2301         d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
2302         d.show();
2303     }
2304 
2305     /**
2306      * Post an alert for user confirmation when sending to a potential short code.
2307      *
2308      * @param isPremium true if the destination is known to be a premium short code
2309      * @param trackers the SmsTracker array for the current message.
2310      */
2311     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
handleConfirmShortCode(boolean isPremium, SmsTracker[] trackers)2312     protected void handleConfirmShortCode(boolean isPremium, SmsTracker[] trackers) {
2313         if (denyIfQueueLimitReached(trackers)) {
2314             return;     // queue limit reached; error was returned to caller
2315         }
2316 
2317         int detailsId;
2318         if (isPremium) {
2319             detailsId = R.string.sms_premium_short_code_details;
2320         } else {
2321             detailsId = R.string.sms_short_code_details;
2322         }
2323 
2324         CharSequence appLabel = getAppLabel(trackers[0].getAppPackageName(), trackers[0].mUserId);
2325         Resources r = Resources.getSystem();
2326         Spanned messageText =
2327                 Html.fromHtml(
2328                         r.getString(
2329                                 R.string.sms_short_code_confirm_message,
2330                                 appLabel,
2331                                 trackers[0].mDestAddress));
2332 
2333         LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
2334                 Context.LAYOUT_INFLATER_SERVICE);
2335         View layout = inflater.inflate(R.layout.sms_short_code_confirmation_dialog, null);
2336 
2337         // Construct ConfirmDialogListenter for short code message sending
2338         ConfirmDialogListener listener =
2339                 new ConfirmDialogListener(
2340                         trackers,
2341                         (TextView)
2342                                 layout.findViewById(R.id.sms_short_code_remember_undo_instruction),
2343                         ConfirmDialogListener.SHORT_CODE_MSG);
2344 
2345         TextView messageView = (TextView) layout.findViewById(R.id.sms_short_code_confirm_message);
2346         messageView.setText(messageText);
2347 
2348         ViewGroup detailsLayout = (ViewGroup) layout.findViewById(
2349                 R.id.sms_short_code_detail_layout);
2350         TextView detailsView = (TextView) detailsLayout.findViewById(
2351                 R.id.sms_short_code_detail_message);
2352         detailsView.setText(detailsId);
2353 
2354         CheckBox rememberChoice = (CheckBox) layout.findViewById(
2355                 R.id.sms_short_code_remember_choice_checkbox);
2356         rememberChoice.setOnCheckedChangeListener(listener);
2357 
2358         AlertDialog d = new AlertDialog.Builder(mContext)
2359                 .setView(layout)
2360                 .setPositiveButton(r.getString(R.string.sms_short_code_confirm_allow), listener)
2361                 .setNegativeButton(r.getString(R.string.sms_short_code_confirm_deny), listener)
2362                 .setOnCancelListener(listener)
2363                 .create();
2364 
2365         d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
2366         d.show();
2367 
2368         listener.setPositiveButton(d.getButton(DialogInterface.BUTTON_POSITIVE));
2369         listener.setNegativeButton(d.getButton(DialogInterface.BUTTON_NEGATIVE));
2370     }
2371 
2372     /**
2373      * Send the message along to the radio.
2374      *
2375      * @param tracker holds the SMS message to send
2376      */
2377     @UnsupportedAppUsage
sendSms(SmsTracker tracker)2378     protected abstract void sendSms(SmsTracker tracker);
2379 
2380     /**
2381      * Retry the message along to the radio.
2382      *
2383      * @param tracker holds the SMS message to send
2384      */
sendRetrySms(SmsTracker tracker)2385     public void sendRetrySms(SmsTracker tracker) {
2386         // re-routing to SmsDispatchersController
2387         if (mSmsDispatchersController != null) {
2388             mSmsDispatchersController.sendRetrySms(tracker);
2389         } else {
2390             Rlog.e(TAG, mSmsDispatchersController + " is null. Retry failed "
2391                     + SmsController.formatCrossStackMessageId(tracker.mMessageId));
2392         }
2393     }
2394 
handleSmsTrackersFailure(SmsTracker[] trackers, @SmsManager.Result int error, int errorCode)2395     private void handleSmsTrackersFailure(SmsTracker[] trackers, @SmsManager.Result int error,
2396             int errorCode) {
2397         for (SmsTracker tracker : trackers) {
2398             tracker.onFailed(mContext, error, errorCode);
2399             notifySmsSentFailedToEmergencyStateTracker(tracker, false);
2400         }
2401         if (trackers.length > 0) {
2402             // This error occurs before the SMS is sent. Make an assumption if it would have
2403             // been sent over IMS or not.
2404             mPhone.getSmsStats().onOutgoingSms(
2405                     isIms(),
2406                     SmsConstants.FORMAT_3GPP2.equals(getFormat()),
2407                     false /* fallbackToCs */,
2408                     error,
2409                     trackers[0].mMessageId,
2410                     trackers[0].isFromDefaultSmsApplication(mContext),
2411                     trackers[0].getInterval(),
2412                     mTelephonyManager.isEmergencyNumber(trackers[0].mDestAddress));
2413             if (mPhone != null) {
2414                 TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
2415                 if (telephonyAnalytics != null) {
2416                     SmsMmsAnalytics smsMmsAnalytics = telephonyAnalytics.getSmsMmsAnalytics();
2417                     if (smsMmsAnalytics != null) {
2418                         smsMmsAnalytics.onOutgoingSms(
2419                                 isIms(),
2420                                 error);
2421                     }
2422                 }
2423             }
2424         }
2425     }
2426 
2427     /**
2428      * Keeps track of an SMS that has been sent to the RIL, until it has
2429      * successfully been sent, or we're done trying.
2430      */
2431     public static class SmsTracker {
2432         // fields need to be public for derived SmsDispatchers
2433         @UnsupportedAppUsage
2434         private final HashMap<String, Object> mData;
2435         public int mRetryCount;
2436         // IMS retry counter. Nonzero indicates initial message was sent over IMS channel in RIL and
2437         // counts how many retries have been made on the IMS channel.
2438         // Used in older implementations where the message is sent over IMS using the RIL.
2439         public int mImsRetry;
2440         // Tag indicating that this SMS is being handled by the ImsSmsDispatcher. This tracker
2441         // should not try to use SMS over IMS over the RIL interface in this case when falling back.
2442         public boolean mUsesImsServiceForIms;
2443         @UnsupportedAppUsage
2444         public int mMessageRef;
2445         public boolean mExpectMore;
2446         public int mValidityPeriod;
2447         public int mPriority;
2448         String mFormat;
2449 
2450         @UnsupportedAppUsage
2451         public final PendingIntent mSentIntent;
2452         @UnsupportedAppUsage
2453         public final PendingIntent mDeliveryIntent;
2454 
2455         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2456         public final PackageInfo mAppInfo;
2457         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2458         public final String mDestAddress;
2459 
2460         public final SmsHeader mSmsHeader;
2461 
2462         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2463         private long mTimestamp = SystemClock.elapsedRealtime();
2464         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2465         public Uri mMessageUri; // Uri of persisted message if we wrote one
2466 
2467         // Reference to states of a multipart message that this part belongs to
2468         private AtomicInteger mUnsentPartCount;
2469         private AtomicBoolean mAnyPartFailed;
2470         // The full message content of a single part message
2471         // or a multipart message that this part belongs to
2472         private String mFullMessageText;
2473 
2474         private int mSubId;
2475 
2476         // If this is a text message (instead of data message)
2477         private boolean mIsText;
2478 
2479         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2480         private boolean mPersistMessage;
2481 
2482         // User who sends the SMS.
2483         private final @UserIdInt int mUserId;
2484 
2485         private final boolean mIsForVvm;
2486 
2487         public final long mMessageId;
2488 
2489         private Boolean mIsFromDefaultSmsApplication;
2490 
2491         private int mCarrierId;
2492         private boolean mSkipShortCodeDestAddrCheck;
2493         // SMS anomaly uuid -- unexpected error from RIL
2494         private final UUID mAnomalyUnexpectedErrorFromRilUUID =
2495                 UUID.fromString("43043600-ea7a-44d2-9ae6-a58567ac7886");
2496 
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, long messageId, int carrierId, int messageRef, boolean skipShortCodeDestAddrCheck)2497         private SmsTracker(HashMap<String, Object> data, PendingIntent sentIntent,
2498                 PendingIntent deliveryIntent, PackageInfo appInfo, String destAddr, String format,
2499                 AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
2500                 SmsHeader smsHeader, boolean expectMore, String fullMessageText, int subId,
2501                 boolean isText, boolean persistMessage, int userId, int priority,
2502                 int validityPeriod, boolean isForVvm, long messageId, int carrierId,
2503                 int messageRef, boolean skipShortCodeDestAddrCheck) {
2504             mData = data;
2505             mSentIntent = sentIntent;
2506             mDeliveryIntent = deliveryIntent;
2507             mRetryCount = 0;
2508             mAppInfo = appInfo;
2509             mDestAddress = destAddr;
2510             mFormat = format;
2511             mExpectMore = expectMore;
2512             mImsRetry = 0;
2513             mUsesImsServiceForIms = false;
2514             mMessageRef = messageRef;
2515             mUnsentPartCount = unsentPartCount;
2516             mAnyPartFailed = anyPartFailed;
2517             mMessageUri = messageUri;
2518             mSmsHeader = smsHeader;
2519             mFullMessageText = fullMessageText;
2520             mSubId = subId;
2521             mIsText = isText;
2522             mPersistMessage = persistMessage;
2523             mUserId = userId;
2524             mPriority = priority;
2525             mValidityPeriod = validityPeriod;
2526             mIsForVvm = isForVvm;
2527             mMessageId = messageId;
2528             mCarrierId = carrierId;
2529             mSkipShortCodeDestAddrCheck = skipShortCodeDestAddrCheck;
2530         }
2531 
getData()2532         public HashMap<String, Object> getData() {
2533             return mData;
2534         }
2535 
2536         /**
2537          * Get the App package name
2538          * @return App package name info
2539          */
getAppPackageName()2540         public String getAppPackageName() {
2541             return mAppInfo != null ? mAppInfo.packageName : null;
2542         }
2543 
2544         /**
2545          * Get the calling Application Info
2546          * @return Application Info
2547          */
getAppInfo()2548         public ApplicationInfo getAppInfo() {
2549             return mAppInfo == null ? null : mAppInfo.applicationInfo;
2550         }
2551 
2552         /** Return if the SMS was originated from the default SMS application. */
isFromDefaultSmsApplication(Context context)2553         public boolean isFromDefaultSmsApplication(Context context) {
2554             if (mIsFromDefaultSmsApplication == null) {
2555                 UserHandle userHandle;
2556                 final long identity = Binder.clearCallingIdentity();
2557                 try {
2558                     userHandle = TelephonyUtils.getSubscriptionUserHandle(context, mSubId);
2559                 } finally {
2560                     Binder.restoreCallingIdentity(identity);
2561                 }
2562                 // Perform a lazy initialization, due to the cost of the operation.
2563                 mIsFromDefaultSmsApplication = SmsApplication.isDefaultSmsApplicationAsUser(context,
2564                                     getAppPackageName(), userHandle);
2565             }
2566             return mIsFromDefaultSmsApplication;
2567         }
2568 
2569         /**
2570          * Update the status of this message if we persisted it
2571          */
2572         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
updateSentMessageStatus(Context context, int status)2573         public void updateSentMessageStatus(Context context, int status) {
2574             if (mMessageUri != null) {
2575                 // If we wrote this message in writeSentMessage, update it now
2576                 ContentValues values = new ContentValues(1);
2577                 values.put(Sms.STATUS, status);
2578                 context.getContentResolver().update(mMessageUri, values, null, null);
2579             }
2580         }
2581 
2582         /**
2583          * Set the final state of a message: FAILED or SENT
2584          *
2585          * @param context The Context
2586          * @param messageType The final message type
2587          * @param errorCode The error code
2588          */
updateMessageState(Context context, int messageType, int errorCode)2589         private void updateMessageState(Context context, int messageType, int errorCode) {
2590             if (mMessageUri == null) {
2591                 return;
2592             }
2593             final ContentValues values = new ContentValues(2);
2594             values.put(Sms.TYPE, messageType);
2595             values.put(Sms.ERROR_CODE, errorCode);
2596             final long identity = Binder.clearCallingIdentity();
2597             try {
2598                 if (context.getContentResolver().update(mMessageUri, values,
2599                         null/*where*/, null/*selectionArgs*/) != 1) {
2600                     Rlog.e(TAG, "Failed to move message to " + messageType);
2601                 }
2602             } finally {
2603                 Binder.restoreCallingIdentity(identity);
2604             }
2605         }
2606 
2607         /**
2608          * Returns the interval in milliseconds between sending the message out and current time.
2609          * Called after receiving success/failure response to calculate the time
2610          * to complete the SMS send to the network.
2611          */
getInterval()2612         protected long getInterval() {
2613             return SystemClock.elapsedRealtime() - mTimestamp;
2614         }
2615 
2616         /**
2617          * Returns the flag specifying whether this {@link SmsTracker} is a single part or
2618          * the last part of multipart message.
2619          */
isSinglePartOrLastPart()2620         protected boolean isSinglePartOrLastPart() {
2621             return mUnsentPartCount != null ? (mUnsentPartCount.get() == 0) : true;
2622         }
2623 
2624         /**
2625          * Persist a sent SMS if required:
2626          * 1. It is a text message
2627          * 2. SmsApplication tells us to persist: sent from apps that are not default-SMS app or
2628          *    bluetooth
2629          *
2630          * @param context
2631          * @param messageType The folder to store (FAILED or SENT)
2632          * @param errorCode The current error code for this SMS or SMS part
2633          * @return The telephony provider URI if stored
2634          */
persistSentMessageIfRequired(Context context, int messageType, int errorCode)2635         private Uri persistSentMessageIfRequired(Context context, int messageType, int errorCode) {
2636             if (!mIsText || !mPersistMessage || isFromDefaultSmsApplication(context)) {
2637                 return null;
2638             }
2639             Rlog.d(TAG, "Persist SMS into "
2640                     + (messageType == Sms.MESSAGE_TYPE_FAILED ? "FAILED" : "SENT"));
2641             final ContentValues values = new ContentValues();
2642             values.put(Sms.SUBSCRIPTION_ID, mSubId);
2643             values.put(Sms.ADDRESS, mDestAddress);
2644             values.put(Sms.BODY, mFullMessageText);
2645             values.put(Sms.DATE, System.currentTimeMillis()); // milliseconds
2646             values.put(Sms.SEEN, 1);
2647             values.put(Sms.READ, 1);
2648             final String creator = mAppInfo != null ? mAppInfo.packageName : null;
2649             if (!TextUtils.isEmpty(creator)) {
2650                 values.put(Sms.CREATOR, creator);
2651             }
2652             if (mDeliveryIntent != null) {
2653                 values.put(Sms.STATUS, Telephony.Sms.STATUS_PENDING);
2654             }
2655             if (errorCode != NO_ERROR_CODE) {
2656                 values.put(Sms.ERROR_CODE, errorCode);
2657             }
2658             final long identity = Binder.clearCallingIdentity();
2659             final ContentResolver resolver = context.getContentResolver();
2660             try {
2661                 final Uri uri =  resolver.insert(Telephony.Sms.Sent.CONTENT_URI, values);
2662                 if (uri != null && messageType == Sms.MESSAGE_TYPE_FAILED) {
2663                     // Since we can't persist a message directly into FAILED box,
2664                     // we have to update the column after we persist it into SENT box.
2665                     // The gap between the state change is tiny so I would not expect
2666                     // it to cause any serious problem
2667                     // TODO: we should add a "failed" URI for this in SmsProvider?
2668                     final ContentValues updateValues = new ContentValues(1);
2669                     updateValues.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED);
2670                     resolver.update(uri, updateValues, null/*where*/, null/*selectionArgs*/);
2671                 }
2672                 return uri;
2673             } catch (Exception e) {
2674                 Rlog.e(TAG, "writeOutboxMessage: Failed to persist outbox message", e);
2675                 return null;
2676             } finally {
2677                 Binder.restoreCallingIdentity(identity);
2678             }
2679         }
2680 
2681         /**
2682          * Persist or update an SMS depending on if we send a new message or a stored message
2683          *
2684          * @param context
2685          * @param messageType The message folder for this SMS, FAILED or SENT
2686          * @param errorCode The current error code for this SMS or SMS part
2687          */
persistOrUpdateMessage(Context context, int messageType, int errorCode)2688         private void persistOrUpdateMessage(Context context, int messageType, int errorCode) {
2689             if (mMessageUri != null) {
2690                 updateMessageState(context, messageType, errorCode);
2691             } else {
2692                 mMessageUri = persistSentMessageIfRequired(context, messageType, errorCode);
2693             }
2694         }
2695 
2696         /**
2697          * Handle a failure of a single part message or a part of a multipart message
2698          *
2699          * @param context The Context
2700          * @param error The error to send back with
2701          * @param errorCode
2702          */
2703         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onFailed(Context context, int error, int errorCode)2704         public void onFailed(Context context, int error, int errorCode) {
2705             if (mAnyPartFailed != null) {
2706                 mAnyPartFailed.set(true);
2707             }
2708             // is single part or last part of multipart message
2709             boolean isSinglePartOrLastPart = true;
2710             if (mUnsentPartCount != null) {
2711                 isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0;
2712             }
2713             if (isSinglePartOrLastPart) {
2714                 persistOrUpdateMessage(context, Sms.MESSAGE_TYPE_FAILED, errorCode);
2715             }
2716             if (mSentIntent != null) {
2717                 try {
2718                     // Extra information to send with the sent intent
2719                     Intent fillIn = new Intent();
2720                     if (mMessageUri != null) {
2721                         // Pass this to SMS apps so that they know where it is stored
2722                         fillIn.putExtra("uri", mMessageUri.toString());
2723                     }
2724                     if (errorCode != NO_ERROR_CODE) {
2725                         fillIn.putExtra("errorCode", errorCode);
2726                     }
2727                     if (mUnsentPartCount != null && isSinglePartOrLastPart) {
2728                         // Is multipart and last part
2729                         fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true);
2730                     }
2731                     if (mMessageId != 0L) {
2732                         // Send the id back to the caller so they can verify the message id
2733                         // with the one they passed to SmsManager.
2734                         fillIn.putExtra(MESSAGE_ID_EXTRA, mMessageId);
2735                     }
2736                     fillIn.putExtra("format", mFormat);
2737                     fillIn.putExtra("ims", mUsesImsServiceForIms);
2738                     mSentIntent.send(context, error, fillIn);
2739                 } catch (CanceledException ex) {
2740                     Rlog.e(TAG, "Failed to send result "
2741                             + SmsController.formatCrossStackMessageId(mMessageId));
2742                 }
2743             }
2744             reportAnomaly(error, errorCode);
2745         }
2746 
reportAnomaly(int error, int errorCode)2747         private void reportAnomaly(int error, int errorCode) {
2748             switch (error) {
2749                 // Exclude known failed reason
2750                 case SmsManager.RESULT_ERROR_NO_SERVICE:
2751                 case SmsManager.RESULT_ERROR_RADIO_OFF:
2752                 case SmsManager.RESULT_ERROR_LIMIT_EXCEEDED:
2753                 case SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED:
2754                 case SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED:
2755                 case SmsManager.RESULT_SMS_BLOCKED_DURING_EMERGENCY:
2756                     break;
2757                 // Dump bugreport for analysis
2758                 default:
2759                     String message = "SMS failed";
2760                     Rlog.d(TAG, message + " with error " + error + ", errorCode " + errorCode);
2761                     AnomalyReporter.reportAnomaly(
2762                             generateUUID(error, errorCode), message, mCarrierId);
2763             }
2764         }
2765 
generateUUID(int error, int errorCode)2766         private UUID generateUUID(int error, int errorCode) {
2767             long lerror = error;
2768             long lerrorCode = errorCode;
2769             return new UUID(mAnomalyUnexpectedErrorFromRilUUID.getMostSignificantBits(),
2770                     mAnomalyUnexpectedErrorFromRilUUID.getLeastSignificantBits()
2771                             + ((lerrorCode << 32) + lerror));
2772         }
2773 
2774         /**
2775          * Handle the sent of a single part message or a part of a multipart message
2776          *
2777          * @param context The Context
2778          */
2779         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onSent(Context context)2780         public void onSent(Context context) {
2781             // is single part or last part of multipart message
2782             boolean isSinglePartOrLastPart = true;
2783             if (mUnsentPartCount != null) {
2784                 isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0;
2785             }
2786             if (isSinglePartOrLastPart) {
2787                 int messageType = Sms.MESSAGE_TYPE_SENT;
2788                 if (mAnyPartFailed != null && mAnyPartFailed.get()) {
2789                     messageType = Sms.MESSAGE_TYPE_FAILED;
2790                 }
2791                 persistOrUpdateMessage(context, messageType, NO_ERROR_CODE);
2792             }
2793             if (mSentIntent != null) {
2794                 try {
2795                     // Extra information to send with the sent intent
2796                     Intent fillIn = new Intent();
2797                     if (mMessageUri != null) {
2798                         // Pass this to SMS apps so that they know where it is stored
2799                         fillIn.putExtra("uri", mMessageUri.toString());
2800                     }
2801                     if (mUnsentPartCount != null && isSinglePartOrLastPart) {
2802                         // Is multipart and last part
2803                         fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true);
2804                     }
2805                     fillIn.putExtra("format", mFormat);
2806                     fillIn.putExtra("ims", mUsesImsServiceForIms);
2807                     mSentIntent.send(context, Activity.RESULT_OK, fillIn);
2808                 } catch (CanceledException ex) {
2809                     Rlog.e(TAG, "Failed to send result");
2810                 }
2811             }
2812         }
2813     }
2814 
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, long messageId, int messageRef, boolean skipShortCodeCheck)2815     protected SmsTracker getSmsTracker(String callingPackage, HashMap<String, Object> data,
2816             PendingIntent sentIntent, PendingIntent deliveryIntent, String format,
2817             AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
2818             SmsHeader smsHeader, boolean expectMore, String fullMessageText, boolean isText,
2819             boolean persistMessage, int priority, int validityPeriod, boolean isForVvm,
2820             long messageId, int messageRef, boolean skipShortCodeCheck) {
2821         // Get package info via packagemanager
2822         UserHandle callingUser = UserHandle.getUserHandleForUid(Binder.getCallingUid());
2823         final int userId = callingUser.getIdentifier();
2824         PackageManager pm = mContext.createContextAsUser(callingUser, 0).getPackageManager();
2825         PackageInfo appInfo = null;
2826         try {
2827             appInfo = pm.getPackageInfo(callingPackage, PackageManager.GET_SIGNATURES);
2828         } catch (PackageManager.NameNotFoundException e) {
2829             // error will be logged in sendRawPdu
2830         }
2831         // Strip non-digits from destination phone number before checking for short codes
2832         // and before displaying the number to the user if confirmation is required.
2833         String destAddr = PhoneNumberUtils.extractNetworkPortion((String) data.get("destAddr"));
2834         return new SmsTracker(data, sentIntent, deliveryIntent, appInfo, destAddr, format,
2835                 unsentPartCount, anyPartFailed, messageUri, smsHeader, expectMore,
2836                 fullMessageText, getSubId(), isText, persistMessage, userId, priority,
2837                 validityPeriod, isForVvm, messageId, mPhone.getCarrierId(), messageRef,
2838                 skipShortCodeCheck);
2839     }
2840 
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, long messageId, int messageRef)2841     protected SmsTracker getSmsTracker(String callingPackage, HashMap<String, Object> data,
2842             PendingIntent sentIntent, PendingIntent deliveryIntent, String format, Uri messageUri,
2843             boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage,
2844             boolean isForVvm, long messageId, int messageRef) {
2845         return getSmsTracker(callingPackage, data, sentIntent, deliveryIntent, format,
2846                 null/*unsentPartCount*/, null/*anyPartFailed*/, messageUri, null/*smsHeader*/,
2847                 expectMore, fullMessageText, isText, persistMessage,
2848                 SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, SMS_MESSAGE_PERIOD_NOT_SPECIFIED, isForVvm,
2849                 messageId, messageRef, false);
2850     }
2851 
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, long messageId, int messageRef, boolean skipShortCodeCheck)2852     protected SmsTracker getSmsTracker(String callingPackage, HashMap<String, Object> data,
2853             PendingIntent sentIntent, PendingIntent deliveryIntent, String format, Uri messageUri,
2854             boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage,
2855             int priority, int validityPeriod, boolean isForVvm, long messageId, int messageRef,
2856             boolean skipShortCodeCheck) {
2857         return getSmsTracker(callingPackage, data, sentIntent, deliveryIntent, format,
2858                 null/*unsentPartCount*/, null/*anyPartFailed*/, messageUri, null/*smsHeader*/,
2859                 expectMore, fullMessageText, isText, persistMessage, priority, validityPeriod,
2860                 isForVvm, messageId, messageRef, skipShortCodeCheck);
2861     }
2862 
getSmsTrackerMap(String destAddr, String scAddr, String text, SmsMessageBase.SubmitPduBase pdu)2863     protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
2864             String text, SmsMessageBase.SubmitPduBase pdu) {
2865         HashMap<String, Object> map = new HashMap<String, Object>();
2866         map.put(MAP_KEY_DEST_ADDR, destAddr);
2867         map.put(MAP_KEY_SC_ADDR, scAddr);
2868         map.put(MAP_KEY_TEXT, text);
2869         map.put(MAP_KEY_SMSC, pdu.encodedScAddress);
2870         map.put(MAP_KEY_PDU, pdu.encodedMessage);
2871         return map;
2872     }
2873 
getSmsTrackerMap(String destAddr, String scAddr, int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu)2874     protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
2875             int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu) {
2876         HashMap<String, Object> map = new HashMap<String, Object>();
2877         map.put(MAP_KEY_DEST_ADDR, destAddr);
2878         map.put(MAP_KEY_SC_ADDR, scAddr);
2879         map.put(MAP_KEY_DEST_PORT, destPort);
2880         map.put(MAP_KEY_DATA, data);
2881         map.put(MAP_KEY_SMSC, pdu.encodedScAddress);
2882         map.put(MAP_KEY_PDU, pdu.encodedMessage);
2883         return map;
2884     }
2885 
2886     /**
2887      * Dialog listener for SMS confirmation dialog.
2888      */
2889     private final class ConfirmDialogListener
2890             implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener,
2891             CompoundButton.OnCheckedChangeListener {
2892 
2893         private final SmsTracker[] mTrackers;
2894         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2895         private Button mPositiveButton;
2896         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2897         private Button mNegativeButton;
2898         private boolean mRememberChoice;    // default is unchecked
2899         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2900         private final TextView mRememberUndoInstruction;
2901         private int mConfirmationType;  // 0 - Short Code Msg Sending; 1 - Rate Limit Exceeded
2902         private static final int SHORT_CODE_MSG = 0; // Short Code Msg
2903         private static final int RATE_LIMIT = 1; // Rate Limit Exceeded
2904         private static final int NEVER_ALLOW = 1; // Never Allow
2905 
ConfirmDialogListener(SmsTracker[] trackers, TextView textView, int confirmationType)2906         ConfirmDialogListener(SmsTracker[] trackers, TextView textView, int confirmationType) {
2907             mTrackers = trackers;
2908             mRememberUndoInstruction = textView;
2909             mConfirmationType = confirmationType;
2910         }
2911 
setPositiveButton(Button button)2912         void setPositiveButton(Button button) {
2913             mPositiveButton = button;
2914         }
2915 
setNegativeButton(Button button)2916         void setNegativeButton(Button button) {
2917             mNegativeButton = button;
2918         }
2919 
2920         @Override
onClick(DialogInterface dialog, int which)2921         public void onClick(DialogInterface dialog, int which) {
2922             // Always set the SMS permission so that Settings will show a permission setting
2923             // for the app (it won't be shown until after the app tries to send to a short code).
2924             int newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER;
2925 
2926             if (which == DialogInterface.BUTTON_POSITIVE) {
2927                 Rlog.d(TAG, "CONFIRM sending SMS");
2928                 // XXX this is lossy- apps can have more than one signature
2929                 EventLog.writeEvent(
2930                         EventLogTags.EXP_DET_SMS_SENT_BY_USER,
2931                         mTrackers[0].mAppInfo.applicationInfo == null
2932                                 ? -1
2933                                 : mTrackers[0].mAppInfo.applicationInfo.uid);
2934                 sendMessage(obtainMessage(EVENT_SEND_CONFIRMED_SMS, mTrackers));
2935                 if (mRememberChoice) {
2936                     newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW;
2937                 }
2938             } else if (which == DialogInterface.BUTTON_NEGATIVE) {
2939                 Rlog.d(TAG, "DENY sending SMS");
2940                 // XXX this is lossy- apps can have more than one signature
2941                 EventLog.writeEvent(
2942                         EventLogTags.EXP_DET_SMS_DENIED_BY_USER,
2943                         mTrackers[0].mAppInfo.applicationInfo == null
2944                                 ? -1
2945                                 : mTrackers[0].mAppInfo.applicationInfo.uid);
2946                 Message msg = obtainMessage(EVENT_STOP_SENDING, mTrackers);
2947                 msg.arg1 = mConfirmationType;
2948                 if (mRememberChoice) {
2949                     newSmsPermission = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW;
2950                     msg.arg2 = ConfirmDialogListener.NEVER_ALLOW;
2951                 }
2952                 sendMessage(msg);
2953             }
2954             mSmsDispatchersController.setPremiumSmsPermission(
2955                     mTrackers[0].getAppPackageName(), newSmsPermission);
2956         }
2957 
2958         @Override
onCancel(DialogInterface dialog)2959         public void onCancel(DialogInterface dialog) {
2960             Rlog.d(TAG, "dialog dismissed: don't send SMS");
2961             Message msg = obtainMessage(EVENT_STOP_SENDING, mTrackers);
2962             msg.arg1 = mConfirmationType;
2963             sendMessage(msg);
2964         }
2965 
2966         @Override
onCheckedChanged(CompoundButton buttonView, boolean isChecked)2967         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
2968             Rlog.d(TAG, "remember this choice: " + isChecked);
2969             mRememberChoice = isChecked;
2970             if (isChecked) {
2971                 mPositiveButton.setText(R.string.sms_short_code_confirm_always_allow);
2972                 mNegativeButton.setText(R.string.sms_short_code_confirm_never_allow);
2973                 if (mRememberUndoInstruction != null) {
2974                     mRememberUndoInstruction
2975                             .setText(R.string.sms_short_code_remember_undo_instruction);
2976                     mRememberUndoInstruction.setPadding(0,0,0,32);
2977                 }
2978             } else {
2979                 mPositiveButton.setText(R.string.sms_short_code_confirm_allow);
2980                 mNegativeButton.setText(R.string.sms_short_code_confirm_deny);
2981                 if (mRememberUndoInstruction != null) {
2982                     mRememberUndoInstruction.setText("");
2983                     mRememberUndoInstruction.setPadding(0,0,0,0);
2984                 }
2985             }
2986         }
2987     }
2988 
isIms()2989     public boolean isIms() {
2990         if (mSmsDispatchersController != null) {
2991             return mSmsDispatchersController.isIms();
2992         } else {
2993             Rlog.e(TAG, "mSmsDispatchersController is null");
2994             return false;
2995         }
2996     }
2997 
2998     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getMultipartMessageText(ArrayList<String> parts)2999     private String getMultipartMessageText(ArrayList<String> parts) {
3000         final StringBuilder sb = new StringBuilder();
3001         for (String part : parts) {
3002             if (part != null) {
3003                 sb.append(part);
3004             }
3005         }
3006         return sb.toString();
3007     }
3008 
3009     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getCarrierAppPackageName()3010     protected String getCarrierAppPackageName() {
3011         CarrierPrivilegesTracker cpt = mPhone.getCarrierPrivilegesTracker();
3012         if (cpt == null) {
3013             return null;
3014         }
3015         List<String> carrierPackages =
3016                 cpt.getCarrierPackageNamesForIntent(
3017                         new Intent(CarrierMessagingService.SERVICE_INTERFACE));
3018         if (carrierPackages != null && carrierPackages.size() == 1) {
3019             return carrierPackages.get(0);
3020         }
3021         // If there is no carrier package which implements CarrierMessagingService, then lookup
3022         // an ImsService implementing RCS that also implements CarrierMessagingService.
3023         return CarrierSmsUtils.getImsRcsPackageForIntent(mContext, mPhone,
3024                 new Intent(CarrierMessagingService.SERVICE_INTERFACE));
3025     }
3026 
3027     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getSubId()3028     protected int getSubId() {
3029         return SubscriptionManager.getSubscriptionId(mPhone.getPhoneId());
3030     }
3031 
3032     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
checkCallerIsPhoneOrCarrierApp()3033     private void checkCallerIsPhoneOrCarrierApp() {
3034         int uid = Binder.getCallingUid();
3035         int appId = UserHandle.getAppId(uid);
3036         if (appId == Process.PHONE_UID || uid == 0) {
3037             return;
3038         }
3039         try {
3040             PackageManager pm = mContext.getPackageManager();
3041             ApplicationInfo ai = pm.getApplicationInfo(getCarrierAppPackageName(), 0);
3042             if (UserHandle.getAppId(ai.uid) != UserHandle.getAppId(Binder.getCallingUid())) {
3043                 throw new SecurityException("Caller is not phone or carrier app!");
3044             }
3045         } catch (PackageManager.NameNotFoundException re) {
3046             throw new SecurityException("Caller is not phone or carrier app!");
3047         }
3048     }
3049 
isCdmaMo()3050     protected boolean isCdmaMo() {
3051         return mSmsDispatchersController.isCdmaMo();
3052     }
3053 
isAscii7bitSupportedForLongMessage()3054     private boolean isAscii7bitSupportedForLongMessage() {
3055         //TODO: Do not rely on calling identity here, we should store UID & clear identity earlier.
3056         long token = Binder.clearCallingIdentity();
3057         try {
3058             CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(
3059                     Context.CARRIER_CONFIG_SERVICE);
3060             PersistableBundle pb = null;
3061             pb = configManager.getConfigForSubId(mPhone.getSubId());
3062             if (pb != null) {
3063                 return pb.getBoolean(CarrierConfigManager
3064                         .KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL);
3065             }
3066             return false;
3067         } finally {
3068             Binder.restoreCallingIdentity(token);
3069         }
3070     }
3071 
3072     /**
3073      * Dump local logs
3074      */
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)3075     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
3076         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
3077         pw.println(TAG);
3078         pw.increaseIndent();
3079 
3080         pw.println("mLocalLog:");
3081         pw.increaseIndent();
3082         mLocalLog.dump(fd, pw, args);
3083         pw.decreaseIndent();
3084 
3085         pw.println("mSmsOutgoingErrorCodes:");
3086         pw.increaseIndent();
3087         mSmsOutgoingErrorCodes.dump(fd, pw, args);
3088         pw.decreaseIndent();
3089 
3090         pw.decreaseIndent();
3091     }
3092 }
3093