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