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