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