• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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.telephony.SmsManager.STATUS_ON_ICC_FREE;
20 import static android.telephony.SmsManager.STATUS_ON_ICC_READ;
21 import static android.telephony.SmsManager.STATUS_ON_ICC_UNREAD;
22 
23 import android.Manifest;
24 import android.annotation.NonNull;
25 import android.annotation.RequiresPermission;
26 import android.app.AppOpsManager;
27 import android.app.PendingIntent;
28 import android.compat.annotation.UnsupportedAppUsage;
29 import android.content.ContentResolver;
30 import android.content.Context;
31 import android.content.pm.PackageManager;
32 import android.database.Cursor;
33 import android.database.sqlite.SQLiteException;
34 import android.net.Uri;
35 import android.os.AsyncResult;
36 import android.os.Binder;
37 import android.os.Build;
38 import android.os.Handler;
39 import android.os.Looper;
40 import android.os.Message;
41 import android.provider.Telephony;
42 import android.telephony.SmsCbMessage;
43 import android.telephony.SmsManager;
44 import android.telephony.SmsMessage;
45 import android.telephony.emergency.EmergencyNumber;
46 import android.util.LocalLog;
47 import android.util.Log;
48 
49 import com.android.internal.annotations.VisibleForTesting;
50 import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
51 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
52 import com.android.internal.telephony.flags.FeatureFlags;
53 import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
54 import com.android.internal.telephony.uicc.IccConstants;
55 import com.android.internal.telephony.uicc.IccFileHandler;
56 import com.android.internal.telephony.uicc.IccUtils;
57 import com.android.internal.telephony.uicc.UiccController;
58 import com.android.internal.telephony.uicc.UiccProfile;
59 import com.android.internal.util.HexDump;
60 import com.android.telephony.Rlog;
61 
62 import java.io.FileDescriptor;
63 import java.io.PrintWriter;
64 import java.util.ArrayList;
65 import java.util.Arrays;
66 import java.util.List;
67 import java.util.concurrent.atomic.AtomicBoolean;
68 
69 /**
70  * IccSmsInterfaceManager to provide an inter-process communication to
71  * access Sms in Icc.
72  */
73 public class IccSmsInterfaceManager {
74     static final String LOG_TAG = "IccSmsInterfaceManager";
75     static final boolean DBG = true;
76 
77     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
78     private CellBroadcastRangeManager mCellBroadcastRangeManager =
79             new CellBroadcastRangeManager();
80     private CdmaBroadcastRangeManager mCdmaBroadcastRangeManager =
81             new CdmaBroadcastRangeManager();
82 
83     private static final int EVENT_LOAD_DONE = 1;
84     private static final int EVENT_UPDATE_DONE = 2;
85     protected static final int EVENT_SET_BROADCAST_ACTIVATION_DONE = 3;
86     protected static final int EVENT_SET_BROADCAST_CONFIG_DONE = 4;
87     private static final int EVENT_GET_SMSC_DONE = 5;
88     private static final int EVENT_SET_SMSC_DONE = 6;
89     private static final int SMS_CB_CODE_SCHEME_MIN = 0;
90     private static final int SMS_CB_CODE_SCHEME_MAX = 255;
91     public static final int SMS_MESSAGE_PRIORITY_NOT_SPECIFIED = -1;
92     public static final int SMS_MESSAGE_PERIOD_NOT_SPECIFIED = -1;
93 
94     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
95     protected Phone mPhone;
96     @UnsupportedAppUsage
97     final protected Context mContext;
98     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
99     final protected AppOpsManager mAppOps;
100     public SmsDispatchersController mDispatchersController;
101     private SmsPermissions mSmsPermissions;
102 
103     private final LocalLog mCellBroadcastLocalLog = new LocalLog(64);
104 
105     private static final class Request {
106         AtomicBoolean mStatus = new AtomicBoolean(false);
107         Object mResult = null;
108     }
109 
110     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
111     protected Handler mHandler = new Handler() {
112         @Override
113         public void handleMessage(Message msg) {
114             AsyncResult ar = (AsyncResult) msg.obj;
115             Request request = (Request) ar.userObj;
116 
117             switch (msg.what) {
118                 case EVENT_UPDATE_DONE:
119                 case EVENT_SET_BROADCAST_ACTIVATION_DONE:
120                 case EVENT_SET_BROADCAST_CONFIG_DONE:
121                 case EVENT_SET_SMSC_DONE:
122                     notifyPending(request, ar.exception == null);
123                     break;
124                 case EVENT_LOAD_DONE:
125                     List<SmsRawData> smsRawDataList = null;
126                     if (ar.exception == null) {
127                         smsRawDataList = buildValidRawData((ArrayList<byte[]>) ar.result);
128                         //Mark SMS as read after importing it from card.
129                         markMessagesAsRead((ArrayList<byte[]>) ar.result);
130                     } else {
131                         if (Rlog.isLoggable("SMS", Log.DEBUG)) {
132                             loge("Cannot load Sms records");
133                         }
134                     }
135                     notifyPending(request, smsRawDataList);
136                     break;
137                 case EVENT_GET_SMSC_DONE:
138                     String smsc = null;
139                     if (ar.exception == null) {
140                         smsc = (String) ar.result;
141                     } else {
142                         loge("Cannot read SMSC");
143                     }
144                     notifyPending(request, smsc);
145                     break;
146             }
147         }
148 
149         private void notifyPending(Request request, Object result) {
150             if (request != null) {
151                 synchronized (request) {
152                     request.mResult = result;
153                     request.mStatus.set(true);
154                     request.notifyAll();
155                 }
156             }
157         }
158     };
159 
IccSmsInterfaceManager(Phone phone, @NonNull FeatureFlags featureFlags)160     protected IccSmsInterfaceManager(Phone phone, @NonNull FeatureFlags featureFlags) {
161         this(phone, phone.getContext(),
162                 (AppOpsManager) phone.getContext().getSystemService(Context.APP_OPS_SERVICE),
163                 new SmsDispatchersController(
164                         phone, phone.mSmsStorageMonitor, phone.mSmsUsageMonitor, featureFlags),
165                 new SmsPermissions(phone, phone.getContext(),
166                         (AppOpsManager) phone.getContext().getSystemService(
167                                 Context.APP_OPS_SERVICE)));
168     }
169 
170     @VisibleForTesting
IccSmsInterfaceManager( Phone phone, Context context, AppOpsManager appOps, SmsDispatchersController dispatchersController, SmsPermissions smsPermissions)171     public IccSmsInterfaceManager(
172             Phone phone, Context context, AppOpsManager appOps,
173             SmsDispatchersController dispatchersController, SmsPermissions smsPermissions) {
174         mPhone = phone;
175         mContext = context;
176         mAppOps = appOps;
177         mDispatchersController = dispatchersController;
178         mSmsPermissions = smsPermissions;
179     }
180 
181     /**
182      * PhoneFactory Dependencies for testing.
183      */
184     @VisibleForTesting
185     public interface PhoneFactoryProxy {
getPhone(int index)186         Phone getPhone(int index);
getDefaultPhone()187         Phone getDefaultPhone();
getPhones()188         Phone[] getPhones();
189     }
190 
191     private PhoneFactoryProxy mPhoneFactoryProxy = new PhoneFactoryProxy() {
192         @Override
193         public Phone getPhone(int index) {
194             return PhoneFactory.getPhone(index);
195         }
196 
197         @Override
198         public Phone getDefaultPhone() {
199             return PhoneFactory.getDefaultPhone();
200         }
201 
202         @Override
203         public Phone[] getPhones() {
204             return PhoneFactory.getPhones();
205         }
206     };
207 
208     /**
209      * Overrides PhoneFactory dependencies for testing.
210      */
211     @VisibleForTesting
setPhoneFactoryProxy(PhoneFactoryProxy proxy)212     public void setPhoneFactoryProxy(PhoneFactoryProxy proxy) {
213         mPhoneFactoryProxy = proxy;
214     }
215 
enforceNotOnHandlerThread(String methodName)216     private void enforceNotOnHandlerThread(String methodName) {
217         if (Looper.myLooper() == mHandler.getLooper()) {
218             throw new RuntimeException("This method " + methodName + " will deadlock if called from"
219                     + " the handler's thread.");
220         }
221     }
222 
markMessagesAsRead(ArrayList<byte[]> messages)223     protected void markMessagesAsRead(ArrayList<byte[]> messages) {
224         if (messages == null) {
225             return;
226         }
227 
228         //IccFileHandler can be null, if icc card is absent.
229         IccFileHandler fh = mPhone.getIccFileHandler();
230         if (fh == null) {
231             //shouldn't really happen, as messages are marked as read, only
232             //after importing it from icc.
233             if (Rlog.isLoggable("SMS", Log.DEBUG)) {
234                 loge("markMessagesAsRead - aborting, no icc card present.");
235             }
236             return;
237         }
238 
239         int count = messages.size();
240 
241         for (int i = 0; i < count; i++) {
242             byte[] ba = messages.get(i);
243             if ((ba[0] & 0x07) == STATUS_ON_ICC_UNREAD) {
244                 int n = ba.length;
245                 byte[] nba = new byte[n - 1];
246                 System.arraycopy(ba, 1, nba, 0, n - 1);
247                 byte[] record = makeSmsRecordData(STATUS_ON_ICC_READ, nba);
248                 fh.updateEFLinearFixed(IccConstants.EF_SMS, i + 1, record, null, null);
249                 if (Rlog.isLoggable("SMS", Log.DEBUG)) {
250                     log("SMS " + (i + 1) + " marked as read");
251                 }
252             }
253         }
254     }
255 
256     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
enforceReceiveAndSend(String message)257     protected void enforceReceiveAndSend(String message) {
258         mContext.enforceCallingOrSelfPermission(
259                 Manifest.permission.RECEIVE_SMS, message);
260         mContext.enforceCallingOrSelfPermission(
261                 Manifest.permission.SEND_SMS, message);
262     }
263 
264     /**
265      * Enforce the permission for access messages on ICC
266      */
enforceAccessMessageOnICC(String message)267     private void enforceAccessMessageOnICC(String message) {
268         mContext.enforceCallingOrSelfPermission(
269                 Manifest.permission.ACCESS_MESSAGES_ON_ICC, message);
270     }
271 
272     /**
273      * Update the specified message on the Icc.
274      *
275      * @param index record index of message to update
276      * @param status new message status (STATUS_ON_ICC_READ,
277      *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
278      *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
279      * @param pdu the raw PDU to store
280      * @return success or not
281      *
282      */
283 
284     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
285     public boolean
updateMessageOnIccEf(String callingPackage, int index, int status, byte[] pdu)286     updateMessageOnIccEf(String callingPackage, int index, int status, byte[] pdu) {
287         if (DBG) log("updateMessageOnIccEf: index=" + index +
288                 " status=" + status + " ==> " +
289                 "("+ Arrays.toString(pdu) + ")");
290         enforceReceiveAndSend("Updating message on Icc");
291         enforceAccessMessageOnICC("Updating message on Icc");
292         enforceNotOnHandlerThread("updateMessageOnIccEf");
293         if (mAppOps.noteOp(AppOpsManager.OPSTR_WRITE_ICC_SMS, Binder.getCallingUid(),
294                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
295             return false;
296         }
297         Request updateRequest = new Request();
298         synchronized (updateRequest) {
299             Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE, updateRequest);
300 
301             if ((status & 0x01) == STATUS_ON_ICC_FREE) {
302                 // RIL_REQUEST_DELETE_SMS_ON_SIM vs RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM
303                 // Special case FREE: call deleteSmsOnSim/Ruim instead of
304                 // manipulating the record
305                 // Will eventually fail if icc card is not present.
306                 if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) {
307                     mPhone.mCi.deleteSmsOnSim(index, response);
308                 } else {
309                     mPhone.mCi.deleteSmsOnRuim(index, response);
310                 }
311             } else {
312                 //IccFilehandler can be null if ICC card is not present.
313                 IccFileHandler fh = mPhone.getIccFileHandler();
314                 if (fh == null) {
315                     response.recycle();
316                     return false; /* is false */
317                 }
318                 byte[] record = makeSmsRecordData(status, pdu);
319                 fh.updateEFLinearFixed(
320                         IccConstants.EF_SMS,
321                         index, record, null, response);
322             }
323             waitForResult(updateRequest);
324         }
325         return (boolean) updateRequest.mResult;
326     }
327 
328     /**
329      * Copies a raw SMS PDU to the ICC.
330      *
331      * @param callingPackage the package name of the calling app.
332      * @param status message status. One of these status:
333      *               <code>STATUS_ON_ICC_READ</code>
334      *               <code>STATUS_ON_ICC_UNREAD</code>
335      *               <code>STATUS_ON_ICC_SENT</code>
336      *               <code>STATUS_ON_ICC_UNSENT</code>
337      * @param pdu the raw PDU to store.
338      * @param smsc the SMSC for this message. Null means use default.
339      * @return true for success. Otherwise false.
340      */
341     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
copyMessageToIccEf(String callingPackage, int status, byte[] pdu, byte[] smsc)342     public boolean copyMessageToIccEf(String callingPackage, int status, byte[] pdu, byte[] smsc) {
343         //NOTE smsc not used in RUIM
344         if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " +
345                 "pdu=("+ Arrays.toString(pdu) +
346                 "), smsc=(" + Arrays.toString(smsc) +")");
347         enforceReceiveAndSend("Copying message to Icc");
348         enforceNotOnHandlerThread("copyMessageToIccEf");
349         if (mAppOps.noteOp(AppOpsManager.OPSTR_WRITE_ICC_SMS, Binder.getCallingUid(),
350                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
351             return false;
352         }
353         Request copyRequest = new Request();
354         synchronized (copyRequest) {
355             Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE, copyRequest);
356 
357             //RIL_REQUEST_WRITE_SMS_TO_SIM vs RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM
358             if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) {
359                 mPhone.mCi.writeSmsToSim(status, IccUtils.bytesToHexString(smsc),
360                         IccUtils.bytesToHexString(pdu), response);
361             } else {
362                 mPhone.mCi.writeSmsToRuim(status, pdu, response);
363             }
364 
365             waitForResult(copyRequest);
366         }
367         return (boolean) copyRequest.mResult;
368     }
369 
370     /**
371      * Retrieves all messages currently stored on Icc.
372      *
373      * @return list of SmsRawData of all sms on Icc
374      */
375 
376     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getAllMessagesFromIccEf(String callingPackage)377     public List<SmsRawData> getAllMessagesFromIccEf(String callingPackage) {
378         if (DBG) log("getAllMessagesFromEF");
379 
380         mContext.enforceCallingOrSelfPermission(
381                 Manifest.permission.RECEIVE_SMS,
382                 "Reading messages from Icc");
383         enforceAccessMessageOnICC("Reading messages from Icc");
384         enforceNotOnHandlerThread("getAllMessagesFromIccEf");
385         if (mAppOps.noteOp(AppOpsManager.OPSTR_READ_ICC_SMS, Binder.getCallingUid(),
386                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
387             return new ArrayList<SmsRawData>();
388         }
389         Request getRequest = new Request();
390         synchronized (getRequest) {
391 
392             IccFileHandler fh = mPhone.getIccFileHandler();
393             if (fh == null) {
394                 loge("Cannot load Sms records. No icc card?");
395                 return null;
396             }
397 
398             Message response = mHandler.obtainMessage(EVENT_LOAD_DONE, getRequest);
399             fh.loadEFLinearFixedAll(IccConstants.EF_SMS, response);
400 
401             waitForResult(getRequest);
402         }
403         return (List<SmsRawData>) getRequest.mResult;
404     }
405 
406     /**
407      * A permissions check before passing to {@link IccSmsInterfaceManager#sendDataInternal}.
408      * This method checks if the calling package or itself has the permission to send the data sms.
409      */
sendDataWithSelfPermissions(String callingPackage, int callingUser, String callingAttributionTag, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm)410     public void sendDataWithSelfPermissions(String callingPackage, int callingUser,
411             String callingAttributionTag, String destAddr, String scAddr, int destPort, byte[] data,
412             PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm) {
413         if (!mSmsPermissions.checkCallingOrSelfCanSendSms(callingPackage, callingAttributionTag,
414                 "Sending SMS message")) {
415             returnUnspecifiedFailure(sentIntent);
416             return;
417         }
418         sendDataInternal(callingPackage, callingUser, destAddr, scAddr, destPort, data, sentIntent,
419                 deliveryIntent, isForVvm);
420     }
421 
422     /**
423      * @deprecated Use {@link #sendData(String, String, String, String, int, byte[], PendingIntent,
424      * PendingIntent)} instead.
425      */
426     @Deprecated
427     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
sendData(String callingPackage, int callingUser, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)428     public void sendData(String callingPackage, int callingUser, String destAddr, String scAddr,
429             int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
430         sendData(callingPackage, callingUser, null, destAddr, scAddr, destPort, data,
431                 sentIntent, deliveryIntent);
432     }
433 
434     /**
435      * A permissions check before passing to {@link IccSmsInterfaceManager#sendDataInternal}.
436      * This method checks only if the calling package has the permission to send the data sms.
437      */
sendData(String callingPackage, int callingUser, String callingAttributionTag, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)438     public void sendData(String callingPackage, int callingUser, String callingAttributionTag,
439             String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
440             PendingIntent deliveryIntent) {
441         if (!mSmsPermissions.checkCallingCanSendSms(callingPackage, callingAttributionTag,
442                 "Sending SMS message")) {
443             returnUnspecifiedFailure(sentIntent);
444             return;
445         }
446         sendDataInternal(callingPackage, callingUser, destAddr, scAddr, destPort, data, sentIntent,
447                 deliveryIntent, false /* isForVvm */);
448     }
449 
450     /**
451      * Send a data based SMS to a specific application port.
452      *
453      * @param callingPackage the package name of the calling app
454      * @param destAddr the address to send the message to
455      * @param scAddr is the service center address or null to use
456      *  the current default SMSC
457      * @param destPort the port to deliver the message to
458      * @param data the body of the message to send
459      * @param sentIntent if not NULL this <code>PendingIntent</code> is
460      *  broadcast when the message is successfully sent, or failed.
461      *  The result code will be <code>Activity.RESULT_OK<code> for success,
462      *  or one of these errors:<br>
463      *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
464      *  <code>RESULT_ERROR_RADIO_OFF</code><br>
465      *  <code>RESULT_ERROR_NULL_PDU</code><br>
466      *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
467      *  the extra "errorCode" containing a radio technology specific value,
468      *  generally only useful for troubleshooting.<br>
469      *  The per-application based SMS control checks sentIntent. If sentIntent
470      *  is NULL the caller will be checked against all unknown applications,
471      *  which cause smaller number of SMS to be sent in checking period.
472      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
473      *  broadcast when the message is delivered to the recipient.  The
474      *  raw pdu of the status report is in the extended data ("pdu").
475      */
476 
sendDataInternal(String callingPackage, int callinUser, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm)477     private void sendDataInternal(String callingPackage, int callinUser, String destAddr,
478             String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
479             PendingIntent deliveryIntent, boolean isForVvm) {
480         if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
481             log("sendData: destAddr=" + destAddr + " scAddr=" + scAddr + " destPort="
482                     + destPort + " data='" + HexDump.toHexString(data)  + "' sentIntent="
483                     + sentIntent + " deliveryIntent=" + deliveryIntent + " isForVVM=" + isForVvm);
484         }
485         destAddr = filterDestAddress(destAddr);
486         mDispatchersController.sendData(callingPackage, callinUser, destAddr, scAddr,
487                 destPort, data, sentIntent, deliveryIntent, isForVvm);
488     }
489 
490     /**
491      * A permissions check before passing to {@link IccSmsInterfaceManager#sendTextInternal}.
492      * This method checks only if the calling package has the permission to send the sms.
493      * Note: SEND_SMS permission should be checked by the caller of this method
494      */
sendText(String callingPackage, int callingUser, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp, long messageId, boolean skipShortCodeCheck)495     public void sendText(String callingPackage, int callingUser, String destAddr, String scAddr,
496             String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
497             boolean persistMessageForNonDefaultSmsApp, long messageId, boolean skipShortCodeCheck) {
498         sendTextInternal(callingPackage, callingUser, destAddr, scAddr, text, sentIntent,
499                 deliveryIntent, persistMessageForNonDefaultSmsApp,
500                 SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, false /* expectMore */,
501                 SMS_MESSAGE_PERIOD_NOT_SPECIFIED, false /* isForVvm */,
502                 messageId, skipShortCodeCheck);
503     }
504 
505     /**
506      * A permissions check before passing to {@link IccSmsInterfaceManager#sendTextInternal}.
507      * This method checks if the calling package or itself has the permission to send the sms.
508      */
sendTextWithSelfPermissions(String callingPackage, int callingUser, String callingAttributeTag, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage, boolean isForVvm)509     public void sendTextWithSelfPermissions(String callingPackage, int callingUser,
510             String callingAttributeTag, String destAddr, String scAddr, String text,
511             PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage,
512             boolean isForVvm) {
513         if (!mSmsPermissions.checkCallingOrSelfCanSendSms(callingPackage, callingAttributeTag,
514                 "Sending SMS message")) {
515             returnUnspecifiedFailure(sentIntent);
516             return;
517         }
518         sendTextInternal(callingPackage, callingUser, destAddr, scAddr, text, sentIntent,
519                 deliveryIntent, persistMessage, SMS_MESSAGE_PRIORITY_NOT_SPECIFIED,
520                 false /* expectMore */, SMS_MESSAGE_PERIOD_NOT_SPECIFIED,
521                 isForVvm, 0L /* messageId */);
522     }
523 
524 
sendTextInternal(String callingPackage, int callingUser, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore, int validityPeriod, boolean isForVvm, long messageId)525     private void sendTextInternal(String callingPackage, int callingUser, String destAddr,
526             String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
527             boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore,
528             int validityPeriod, boolean isForVvm, long messageId) {
529         sendTextInternal(callingPackage, callingUser, destAddr, scAddr, text, sentIntent,
530                 deliveryIntent, persistMessageForNonDefaultSmsApp, priority, expectMore,
531                 validityPeriod, isForVvm, messageId, false);
532     }
533 
534     /**
535      * Send a text based SMS.
536      *
537      * @param destAddr the address to send the message to
538      * @param scAddr is the service center address or null to use
539      *  the current default SMSC
540      * @param text the body of the message to send
541      * @param sentIntent if not NULL this <code>PendingIntent</code> is
542      *  broadcast when the message is successfully sent, or failed.
543      *  The result code will be <code>Activity.RESULT_OK<code> for success,
544      *  or one of these errors:<br>
545      *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
546      *  <code>RESULT_ERROR_RADIO_OFF</code><br>
547      *  <code>RESULT_ERROR_NULL_PDU</code><br>
548      *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
549      *  the extra "errorCode" containing a radio technology specific value,
550      *  generally only useful for troubleshooting.<br>
551      *  The per-application based SMS control checks sentIntent. If sentIntent
552      *  is NULL the caller will be checked against all unknown applications,
553      *  which cause smaller number of SMS to be sent in checking period.
554      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
555      *  broadcast when the message is delivered to the recipient.  The
556      *  raw pdu of the status report is in the extended data ("pdu").
557      * @param persistMessageForNonDefaultSmsApp whether the sent message should
558      *  be automatically persisted in the SMS db. It only affects messages sent
559      *  by a non-default SMS app. Currently only the carrier app can set this
560      *  parameter to false to skip auto message persistence.
561      * @param priority Priority level of the message
562      *  Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
563      *  ---------------------------------
564      *  PRIORITY      | Level of Priority
565      *  ---------------------------------
566      *      '00'      |     Normal
567      *      '01'      |     Interactive
568      *      '10'      |     Urgent
569      *      '11'      |     Emergency
570      *  ----------------------------------
571      *  Any Other values including negative considered as Invalid Priority Indicator of the message.
572      * @param expectMore is a boolean to indicate the sending messages through same link or not.
573      * @param validityPeriod Validity Period of the message in mins.
574      *  Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
575      *  Validity Period(Minimum) -> 5 mins
576      *  Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
577      *  Any Other values including negative considered as Invalid Validity Period of the message.
578      * @param messageId An id that uniquely identifies the message requested to be sent.
579      *                 Used for logging and diagnostics purposes. The id may be 0.
580      * @param skipShortCodeCheck Skip check for short code type destination address.
581      */
582 
sendTextInternal(String callingPackage, int callingUser, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore, int validityPeriod, boolean isForVvm, long messageId, boolean skipShortCodeCheck)583     private void sendTextInternal(String callingPackage, int callingUser, String destAddr,
584             String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
585             boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore,
586             int validityPeriod, boolean isForVvm, long messageId, boolean skipShortCodeCheck) {
587         if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
588             log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr
589                     + " text='" + text + "' sentIntent=" + sentIntent + " deliveryIntent="
590                     + deliveryIntent + " priority=" + priority + " expectMore=" + expectMore
591                     + " validityPeriod=" + validityPeriod + " isForVVM=" + isForVvm
592                     + " " + SmsController.formatCrossStackMessageId(messageId));
593         }
594         notifyIfOutgoingEmergencySms(destAddr);
595         destAddr = filterDestAddress(destAddr);
596         mDispatchersController.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,
597                 null/*messageUri*/, callingPackage, callingUser, persistMessageForNonDefaultSmsApp,
598                 priority, expectMore, validityPeriod, isForVvm, messageId, skipShortCodeCheck);
599     }
600 
601     /**
602      * Send a text based SMS with Messaging Options.
603      *
604      * @param destAddr the address to send the message to
605      * @param scAddr is the service center address or null to use
606      *  the current default SMSC
607      * @param text the body of the message to send
608      * @param sentIntent if not NULL this <code>PendingIntent</code> is
609      *  broadcast when the message is successfully sent, or failed.
610      *  The result code will be <code>Activity.RESULT_OK<code> for success,
611      *  or one of these errors:<br>
612      *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
613      *  <code>RESULT_ERROR_RADIO_OFF</code><br>
614      *  <code>RESULT_ERROR_NULL_PDU</code><br>
615      *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
616      *  the extra "errorCode" containing a radio technology specific value,
617      *  generally only useful for troubleshooting.<br>
618      *  The per-application based SMS control checks sentIntent. If sentIntent
619      *  is NULL the caller will be checked against all unknown applications,
620      *  which cause smaller number of SMS to be sent in checking period.
621      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
622      *  broadcast when the message is delivered to the recipient.  The
623      *  raw pdu of the status report is in the extended data ("pdu").
624      * @param persistMessageForNonDefaultSmsApp whether the sent message should
625      *  be automatically persisted in the SMS db. It only affects messages sent
626      *  by a non-default SMS app. Currently only the carrier app can set this
627      *  parameter to false to skip auto message persistence.
628      * @param priority Priority level of the message
629      *  Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
630      *  ---------------------------------
631      *  PRIORITY      | Level of Priority
632      *  ---------------------------------
633      *      '00'      |     Normal
634      *      '01'      |     Interactive
635      *      '10'      |     Urgent
636      *      '11'      |     Emergency
637      *  ----------------------------------
638      *  Any Other values including negative considered as Invalid Priority Indicator of the message.
639      * @param expectMore is a boolean to indicate the sending messages through same link or not.
640      * @param validityPeriod Validity Period of the message in mins.
641      *  Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
642      *  Validity Period(Minimum) -> 5 mins
643      *  Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
644      *  Any Other values including negative considered as Invalid Validity Period of the message.
645      */
646 
sendTextWithOptions(String callingPackage, int callingUser, String callingAttributionTag, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore, int validityPeriod)647     public void sendTextWithOptions(String callingPackage, int callingUser,
648             String callingAttributionTag, String destAddr, String scAddr, String text,
649             PendingIntent sentIntent, PendingIntent deliveryIntent,
650             boolean persistMessageForNonDefaultSmsApp, int priority,
651             boolean expectMore, int validityPeriod) {
652         if (!mSmsPermissions.checkCallingCanSendText(persistMessageForNonDefaultSmsApp,
653                     callingPackage, callingAttributionTag, "Sending SMS message")) {
654             returnUnspecifiedFailure(sentIntent);
655             return;
656         }
657         sendTextInternal(callingPackage, callingUser, destAddr, scAddr, text, sentIntent,
658                 deliveryIntent, persistMessageForNonDefaultSmsApp, priority, expectMore,
659                 validityPeriod, false /* isForVvm */, 0L /* messageId */);
660     }
661 
662     /**
663      * Inject an SMS PDU into the android application framework.
664      *
665      * @param pdu is the byte array of pdu to be injected into android application framework
666      * @param format is the format of SMS pdu (3gpp or 3gpp2)
667      * @param receivedIntent if not NULL this <code>PendingIntent</code> is
668      *  broadcast when the message is successfully received by the
669      *  android application framework. This intent is broadcasted at
670      *  the same time an SMS received from radio is acknowledged back.
671      */
672     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent)673     public void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) {
674         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
675                 != PackageManager.PERMISSION_GRANTED) {
676             mSmsPermissions.enforceCallerIsImsAppOrCarrierApp("injectSmsPdu");
677         }
678 
679         if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
680             log("pdu: " + IccUtils.bytesToHexString(pdu)
681                     + "\n format=" + format
682                     + "\n receivedIntent=" + receivedIntent);
683         }
684         mDispatchersController.injectSmsPdu(pdu, format, false /* isOverIms */,
685                 result -> {
686                     if (receivedIntent != null) {
687                         try {
688                             receivedIntent.send(result);
689                         } catch (PendingIntent.CanceledException e) {
690                             loge("receivedIntent cancelled.");
691                         }
692                     }
693                 }
694         );
695     }
696 
697     /**
698      * Send a multi-part text based SMS.
699      *
700      * @param destAddr the address to send the message to
701      * @param scAddr is the service center address or null to use
702      *   the current default SMSC
703      * @param parts an <code>ArrayList</code> of strings that, in order,
704      *   comprise the original message
705      * @param sentIntents if not null, an <code>ArrayList</code> of
706      *   <code>PendingIntent</code>s (one for each message part) that is
707      *   broadcast when the corresponding message part has been sent.
708      *   The result code will be <code>Activity.RESULT_OK<code> for success,
709      *   or one of these errors:
710      *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
711      *   <code>RESULT_ERROR_RADIO_OFF</code>
712      *   <code>RESULT_ERROR_NULL_PDU</code>.
713      *  The per-application based SMS control checks sentIntent. If sentIntent
714      *  is NULL the caller will be checked against all unknown applications,
715      *  which cause smaller number of SMS to be sent in checking period.
716      * @param deliveryIntents if not null, an <code>ArrayList</code> of
717      *   <code>PendingIntent</code>s (one for each message part) that is
718      *   broadcast when the corresponding message part has been delivered
719      *   to the recipient.  The raw pdu of the status report is in the
720      *   extended data ("pdu").
721      * @param messageId An id that uniquely identifies the message requested to be sent.
722      *                 Used for logging and diagnostics purposes. The id may be 0.
723      */
724 
sendMultipartText(String callingPackage, int callingUser, String callingAttributionTag, String destAddr, String scAddr, List<String> parts, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp, long messageId)725     public void sendMultipartText(String callingPackage, int callingUser,
726             String callingAttributionTag, String destAddr, String scAddr, List<String> parts,
727             List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents,
728             boolean persistMessageForNonDefaultSmsApp, long messageId) {
729         sendMultipartTextWithOptions(callingPackage, callingUser, callingAttributionTag, destAddr,
730                 scAddr, parts, sentIntents, deliveryIntents, persistMessageForNonDefaultSmsApp,
731                 SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, false /* expectMore */,
732                 SMS_MESSAGE_PERIOD_NOT_SPECIFIED,
733                 messageId);
734     }
735 
736     /**
737      * Send a multi-part text based SMS with Messaging Options.
738      *
739      * @param destAddr the address to send the message to
740      * @param scAddr is the service center address or null to use
741      *   the current default SMSC
742      * @param parts an <code>ArrayList</code> of strings that, in order,
743      *   comprise the original message
744      * @param sentIntents if not null, an <code>ArrayList</code> of
745      *   <code>PendingIntent</code>s (one for each message part) that is
746      *   broadcast when the corresponding message part has been sent.
747      *   The result code will be <code>Activity.RESULT_OK<code> for success,
748      *   or one of these errors:
749      *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
750      *   <code>RESULT_ERROR_RADIO_OFF</code>
751      *   <code>RESULT_ERROR_NULL_PDU</code>.
752      *  The per-application based SMS control checks sentIntent. If sentIntent
753      *  is NULL the caller will be checked against all unknown applications,
754      *  which cause smaller number of SMS to be sent in checking period.
755      * @param deliveryIntents if not null, an <code>ArrayList</code> of
756      *   <code>PendingIntent</code>s (one for each message part) that is
757      *   broadcast when the corresponding message part has been delivered
758      *   to the recipient.  The raw pdu of the status report is in the
759      *   extended data ("pdu").
760      * @param persistMessageForNonDefaultSmsApp whether the sent message should
761      *   be automatically persisted in the SMS db. It only affects messages sent
762      *   by a non-default SMS app. Currently only the carrier app can set this
763      *   parameter to false to skip auto message persistence.
764      * @param priority Priority level of the message
765      *  Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1
766      *  ---------------------------------
767      *  PRIORITY      | Level of Priority
768      *  ---------------------------------
769      *      '00'      |     Normal
770      *      '01'      |     Interactive
771      *      '10'      |     Urgent
772      *      '11'      |     Emergency
773      *  ----------------------------------
774      *  Any Other values including negative considered as Invalid Priority Indicator of the message.
775      * @param expectMore is a boolean to indicate the sending messages through same link or not.
776      * @param validityPeriod Validity Period of the message in mins.
777      *  Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1.
778      *  Validity Period(Minimum) -> 5 mins
779      *  Validity Period(Maximum) -> 635040 mins(i.e.63 weeks).
780      *  Any Other values including negative considered as Invalid Validity Period of the message.
781      * @param messageId An id that uniquely identifies the message requested to be sent.
782      *                 Used for logging and diagnostics purposes. The id may be 0.
783      */
784 
sendMultipartTextWithOptions(String callingPackage, int callingUser, String callingAttributionTag, String destAddr, String scAddr, List<String> parts, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore, int validityPeriod, long messageId)785     public void sendMultipartTextWithOptions(String callingPackage, int callingUser,
786             String callingAttributionTag, String destAddr, String scAddr, List<String> parts,
787             List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents,
788             boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore,
789             int validityPeriod, long messageId) {
790         if (!mSmsPermissions.checkCallingCanSendText(persistMessageForNonDefaultSmsApp,
791                 callingPackage, callingAttributionTag, "Sending SMS message")) {
792             returnUnspecifiedFailure(sentIntents);
793             return;
794         }
795         if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
796             int i = 0;
797             for (String part : parts) {
798                 log("sendMultipartTextWithOptions: destAddr=" + destAddr + ", srAddr=" + scAddr
799                         + ", part[" + (i++) + "]=" + part
800                         + " " + SmsController.formatCrossStackMessageId(messageId));
801             }
802         }
803         notifyIfOutgoingEmergencySms(destAddr);
804         destAddr = filterDestAddress(destAddr);
805 
806         if (parts.size() > 1 && parts.size() < 10 && !SmsMessage.hasEmsSupport()) {
807             for (int i = 0; i < parts.size(); i++) {
808                 // If EMS is not supported, we have to break down EMS into single segment SMS
809                 // and add page info " x/y".
810                 String singlePart = parts.get(i);
811                 if (SmsMessage.shouldAppendPageNumberAsPrefix()) {
812                     singlePart = String.valueOf(i + 1) + '/' + parts.size() + ' ' + singlePart;
813                 } else {
814                     singlePart = singlePart.concat(' ' + String.valueOf(i + 1) + '/'
815                             + parts.size());
816                 }
817 
818                 PendingIntent singleSentIntent = null;
819                 if (sentIntents != null && sentIntents.size() > i) {
820                     singleSentIntent = sentIntents.get(i);
821                 }
822 
823                 PendingIntent singleDeliveryIntent = null;
824                 if (deliveryIntents != null && deliveryIntents.size() > i) {
825                     singleDeliveryIntent = deliveryIntents.get(i);
826                 }
827 
828                 mDispatchersController.sendText(destAddr, scAddr, singlePart, singleSentIntent,
829                         singleDeliveryIntent, null /* messageUri */, callingPackage, callingUser,
830                         persistMessageForNonDefaultSmsApp, priority, expectMore, validityPeriod,
831                         false /* isForVvm */, messageId);
832             }
833             return;
834         }
835 
836         mDispatchersController.sendMultipartText(destAddr,
837                 scAddr,
838                 (ArrayList<String>) parts,
839                 (ArrayList<PendingIntent>) sentIntents,
840                 (ArrayList<PendingIntent>) deliveryIntents,
841                 null, callingPackage, callingUser, persistMessageForNonDefaultSmsApp,
842                 priority, expectMore, validityPeriod, messageId);
843 
844     }
845 
846     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getPremiumSmsPermission(String packageName)847     public int getPremiumSmsPermission(String packageName) {
848         return mDispatchersController.getPremiumSmsPermission(packageName);
849     }
850 
851 
852     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setPremiumSmsPermission(String packageName, int permission)853     public void setPremiumSmsPermission(String packageName, int permission) {
854         mDispatchersController.setPremiumSmsPermission(packageName, permission);
855     }
856 
857     /**
858      * create SmsRawData lists from all sms record byte[]
859      * Use null to indicate "free" record
860      *
861      * @param messages List of message records from EF_SMS.
862      * @return SmsRawData list of all in-used records
863      */
buildValidRawData(ArrayList<byte[]> messages)864     protected ArrayList<SmsRawData> buildValidRawData(ArrayList<byte[]> messages) {
865         int count = messages.size();
866         ArrayList<SmsRawData> ret;
867 
868         ret = new ArrayList<SmsRawData>(count);
869 
870         for (int i = 0; i < count; i++) {
871             byte[] ba = messages.get(i);
872             if ((ba[0] & 0x01) == STATUS_ON_ICC_FREE) {
873                 ret.add(null);
874             } else {
875                 ret.add(new SmsRawData(messages.get(i)));
876             }
877         }
878 
879         return ret;
880     }
881 
882     /**
883      * Generates an EF_SMS record from status and raw PDU.
884      *
885      * @param status Message status.  See TS 51.011 10.5.3.
886      * @param pdu Raw message PDU.
887      * @return byte array for the record.
888      */
makeSmsRecordData(int status, byte[] pdu)889     protected byte[] makeSmsRecordData(int status, byte[] pdu) {
890         byte[] data;
891         if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) {
892             data = new byte[SmsManager.SMS_RECORD_LENGTH];
893         } else {
894             data = new byte[SmsManager.CDMA_SMS_RECORD_LENGTH];
895         }
896 
897         // Status bits for this record.  See TS 51.011 10.5.3
898         data[0] = (byte) (status & 0x07);
899 
900         System.arraycopy(pdu, 0, data, 1, pdu.length);
901 
902         // Pad out with 0xFF's.
903         for (int j = pdu.length+1; j < data.length; j++) {
904             data[j] = -1;
905         }
906 
907         return data;
908     }
909 
910     /**
911      * Gets the SMSC address from (U)SIM.
912      *
913      * @return the SMSC address string, null if failed.
914      */
getSmscAddressFromIccEf(String callingPackage)915     public String getSmscAddressFromIccEf(String callingPackage) {
916         if (!mSmsPermissions.checkCallingOrSelfCanGetSmscAddress(
917                 callingPackage, "getSmscAddressFromIccEf")) {
918             loge("Caller do not have permission to call GetSmscAddress");
919             return null;
920         }
921         enforceNotOnHandlerThread("getSmscAddressFromIccEf");
922         Request getRequest = new Request();
923         synchronized (getRequest) {
924             Message response = mHandler.obtainMessage(EVENT_GET_SMSC_DONE, getRequest);
925             mPhone.mCi.getSmscAddress(response);
926             waitForResult(getRequest);
927         }
928         return (String) getRequest.mResult;
929     }
930 
931     /**
932      * Sets the SMSC address on (U)SIM.
933      *
934      * @param smsc the SMSC address string.
935      * @return true for success, false otherwise.
936      */
setSmscAddressOnIccEf(String callingPackage, String smsc)937     public boolean setSmscAddressOnIccEf(String callingPackage, String smsc) {
938         if (!mSmsPermissions.checkCallingOrSelfCanSetSmscAddress(
939                 callingPackage, "setSmscAddressOnIccEf")) {
940             loge("Caller do not have permission to call SetSmscAddress");
941             return false;
942         }
943         enforceNotOnHandlerThread("setSmscAddressOnIccEf");
944         Request setRequest = new Request();
945         synchronized (setRequest) {
946             Message response = mHandler.obtainMessage(EVENT_SET_SMSC_DONE, setRequest);
947             mPhone.mCi.setSmscAddress(smsc, response);
948             waitForResult(setRequest);
949         }
950         return (boolean) setRequest.mResult;
951     }
952 
enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType)953     public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
954         mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
955                 "enabling cell broadcast range [" + startMessageId + "-" + endMessageId + "]. "
956                         + "ranType=" + ranType);
957         if (ranType == SmsCbMessage.MESSAGE_FORMAT_3GPP) {
958             return enableGsmBroadcastRange(startMessageId, endMessageId);
959         } else if (ranType == SmsCbMessage.MESSAGE_FORMAT_3GPP2) {
960             return enableCdmaBroadcastRange(startMessageId, endMessageId);
961         } else {
962             throw new IllegalArgumentException("Not a supported RAN Type");
963         }
964     }
965 
disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType)966     public boolean disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
967         mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
968                 "disabling cell broadcast range [" + startMessageId + "-" + endMessageId
969                         + "]. ranType=" + ranType);
970         if (ranType == SmsCbMessage.MESSAGE_FORMAT_3GPP) {
971             return disableGsmBroadcastRange(startMessageId, endMessageId);
972         } else if (ranType == SmsCbMessage.MESSAGE_FORMAT_3GPP2)  {
973             return disableCdmaBroadcastRange(startMessageId, endMessageId);
974         } else {
975             throw new IllegalArgumentException("Not a supported RAN Type");
976         }
977     }
978 
979     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
enableGsmBroadcastRange(int startMessageId, int endMessageId)980     synchronized public boolean enableGsmBroadcastRange(int startMessageId, int endMessageId) {
981 
982         mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
983                 "Enabling cell broadcast SMS");
984 
985         String client = mContext.getPackageManager().getNameForUid(
986                 Binder.getCallingUid());
987 
988         String msg;
989         if (!mCellBroadcastRangeManager.enableRange(startMessageId, endMessageId, client)) {
990             msg = "Failed to add GSM cell broadcast channels range " + startMessageId
991                     + " to " + endMessageId;
992             log(msg);
993             mCellBroadcastLocalLog.log(msg);
994             return false;
995         }
996 
997         if (DBG) {
998             msg = "Added GSM cell broadcast channels range " + startMessageId
999                     + " to " + endMessageId;
1000             log(msg);
1001             mCellBroadcastLocalLog.log(msg);
1002         }
1003 
1004         setCellBroadcastActivation(!mCellBroadcastRangeManager.isEmpty());
1005 
1006         return true;
1007     }
1008 
1009     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
disableGsmBroadcastRange(int startMessageId, int endMessageId)1010     synchronized public boolean disableGsmBroadcastRange(int startMessageId, int endMessageId) {
1011 
1012         mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
1013                 "Disabling cell broadcast SMS");
1014 
1015         String client = mContext.getPackageManager().getNameForUid(
1016                 Binder.getCallingUid());
1017 
1018         String msg;
1019         if (!mCellBroadcastRangeManager.disableRange(startMessageId, endMessageId, client)) {
1020             msg = "Failed to remove GSM cell broadcast channels range " + startMessageId
1021                     + " to " + endMessageId;
1022             log(msg);
1023             mCellBroadcastLocalLog.log(msg);
1024             return false;
1025         }
1026 
1027         if (DBG) {
1028             msg = "Removed GSM cell broadcast channels range " + startMessageId
1029                     + " to " + endMessageId;
1030             log(msg);
1031             mCellBroadcastLocalLog.log(msg);
1032         }
1033 
1034         setCellBroadcastActivation(!mCellBroadcastRangeManager.isEmpty());
1035 
1036         return true;
1037     }
1038 
1039     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
enableCdmaBroadcastRange(int startMessageId, int endMessageId)1040     synchronized public boolean enableCdmaBroadcastRange(int startMessageId, int endMessageId) {
1041 
1042         mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
1043                 "Enabling cdma broadcast SMS");
1044 
1045         String client = mContext.getPackageManager().getNameForUid(
1046                 Binder.getCallingUid());
1047 
1048         String msg;
1049         if (!mCdmaBroadcastRangeManager.enableRange(startMessageId, endMessageId, client)) {
1050             msg = "Failed to add cdma broadcast channels range " + startMessageId + " to "
1051                     + endMessageId;
1052             log(msg);
1053             mCellBroadcastLocalLog.log(msg);
1054             return false;
1055         }
1056 
1057         if (DBG) {
1058             msg = "Added cdma broadcast channels range " + startMessageId + " to " + endMessageId;
1059             log(msg);
1060             mCellBroadcastLocalLog.log(msg);
1061         }
1062 
1063         setCdmaBroadcastActivation(!mCdmaBroadcastRangeManager.isEmpty());
1064 
1065         return true;
1066     }
1067 
1068     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
disableCdmaBroadcastRange(int startMessageId, int endMessageId)1069     synchronized public boolean disableCdmaBroadcastRange(int startMessageId, int endMessageId) {
1070 
1071         mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
1072                 "Disabling cell broadcast SMS");
1073 
1074         String client = mContext.getPackageManager().getNameForUid(
1075                 Binder.getCallingUid());
1076 
1077         String msg;
1078         if (!mCdmaBroadcastRangeManager.disableRange(startMessageId, endMessageId, client)) {
1079             msg = "Failed to remove cdma broadcast channels range " + startMessageId + " to "
1080                     + endMessageId;
1081             log(msg);
1082             mCellBroadcastLocalLog.log(msg);
1083             return false;
1084         }
1085 
1086         if (DBG) {
1087             msg = "Removed cdma broadcast channels range " + startMessageId + " to " + endMessageId;
1088             log(msg);
1089             mCellBroadcastLocalLog.log(msg);
1090         }
1091 
1092         setCdmaBroadcastActivation(!mCdmaBroadcastRangeManager.isEmpty());
1093 
1094         return true;
1095     }
1096 
1097     /**
1098      * Reset all cell broadcast ranges. Previously enabled ranges will become invalid after this.
1099      */
1100     @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS)
resetAllCellBroadcastRanges()1101     public void resetAllCellBroadcastRanges() {
1102         mContext.enforceCallingPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS,
1103                 "resetAllCellBroadcastRanges");
1104         mCdmaBroadcastRangeManager.clearRanges();
1105         mCellBroadcastRangeManager.clearRanges();
1106         log("Cell broadcast ranges reset.");
1107     }
1108 
1109     class CellBroadcastRangeManager extends IntRangeManager {
1110         private ArrayList<SmsBroadcastConfigInfo> mConfigList =
1111                 new ArrayList<SmsBroadcastConfigInfo>();
1112 
1113         /**
1114          * Called when the list of enabled ranges has changed. This will be
1115          * followed by zero or more calls to {@link #addRange} followed by
1116          * a call to {@link #finishUpdate}.
1117          */
startUpdate()1118         protected void startUpdate() {
1119             mConfigList.clear();
1120         }
1121 
1122         /**
1123          * Called after {@link #startUpdate} to indicate a range of enabled
1124          * values.
1125          * @param startId the first id included in the range
1126          * @param endId the last id included in the range
1127          */
addRange(int startId, int endId, boolean selected)1128         protected void addRange(int startId, int endId, boolean selected) {
1129             mConfigList.add(new SmsBroadcastConfigInfo(startId, endId,
1130                         SMS_CB_CODE_SCHEME_MIN, SMS_CB_CODE_SCHEME_MAX, selected));
1131         }
1132 
1133         /**
1134          * Called to indicate the end of a range update started by the
1135          * previous call to {@link #startUpdate}.
1136          * @return true if successful, false otherwise
1137          */
finishUpdate()1138         protected boolean finishUpdate() {
1139             if (mConfigList.isEmpty()) {
1140                 return true;
1141             } else {
1142                 SmsBroadcastConfigInfo[] configs =
1143                         mConfigList.toArray(new SmsBroadcastConfigInfo[mConfigList.size()]);
1144                 return setCellBroadcastConfig(configs);
1145             }
1146         }
1147     }
1148 
1149     class CdmaBroadcastRangeManager extends IntRangeManager {
1150         private ArrayList<CdmaSmsBroadcastConfigInfo> mConfigList =
1151                 new ArrayList<CdmaSmsBroadcastConfigInfo>();
1152 
1153         /**
1154          * Called when the list of enabled ranges has changed. This will be
1155          * followed by zero or more calls to {@link #addRange} followed by a
1156          * call to {@link #finishUpdate}.
1157          */
startUpdate()1158         protected void startUpdate() {
1159             mConfigList.clear();
1160         }
1161 
1162         /**
1163          * Called after {@link #startUpdate} to indicate a range of enabled
1164          * values.
1165          * @param startId the first id included in the range
1166          * @param endId the last id included in the range
1167          */
addRange(int startId, int endId, boolean selected)1168         protected void addRange(int startId, int endId, boolean selected) {
1169             mConfigList.add(new CdmaSmsBroadcastConfigInfo(startId, endId,
1170                     1, selected));
1171         }
1172 
1173         /**
1174          * Called to indicate the end of a range update started by the previous
1175          * call to {@link #startUpdate}.
1176          * @return true if successful, false otherwise
1177          */
finishUpdate()1178         protected boolean finishUpdate() {
1179             if (mConfigList.isEmpty()) {
1180                 return true;
1181             } else {
1182                 CdmaSmsBroadcastConfigInfo[] configs =
1183                         mConfigList.toArray(new CdmaSmsBroadcastConfigInfo[mConfigList.size()]);
1184                 return setCdmaBroadcastConfig(configs);
1185             }
1186         }
1187     }
1188 
1189     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setCellBroadcastConfig(SmsBroadcastConfigInfo[] configs)1190     private boolean setCellBroadcastConfig(SmsBroadcastConfigInfo[] configs) {
1191         if (DBG) {
1192             log("Calling setGsmBroadcastConfig with " + configs.length + " configurations");
1193         }
1194         enforceNotOnHandlerThread("setCellBroadcastConfig");
1195         Request setRequest = new Request();
1196         synchronized (setRequest) {
1197             Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE, setRequest);
1198 
1199             mPhone.mCi.setGsmBroadcastConfig(configs, response);
1200 
1201             waitForResult(setRequest);
1202         }
1203 
1204         return (boolean) setRequest.mResult;
1205     }
1206 
setCellBroadcastActivation(boolean activate)1207     private boolean setCellBroadcastActivation(boolean activate) {
1208         if (DBG) {
1209             log("Calling setCellBroadcastActivation(" + activate + ')');
1210         }
1211 
1212         enforceNotOnHandlerThread("setCellBroadcastConfig");
1213         Request setRequest = new Request();
1214         synchronized (setRequest) {
1215             Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE,
1216                     setRequest);
1217 
1218             mPhone.mCi.setGsmBroadcastActivation(activate, response);
1219             waitForResult(setRequest);
1220         }
1221 
1222         return (boolean) setRequest.mResult;
1223     }
1224 
1225     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs)1226     private boolean setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs) {
1227         if (DBG) {
1228             log("Calling setCdmaBroadcastConfig with " + configs.length + " configurations");
1229         }
1230 
1231         enforceNotOnHandlerThread("setCdmaBroadcastConfig");
1232         Request setRequest = new Request();
1233         synchronized (setRequest) {
1234             Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE, setRequest);
1235 
1236             mPhone.mCi.setCdmaBroadcastConfig(configs, response);
1237 
1238             waitForResult(setRequest);
1239         }
1240 
1241         return (boolean) setRequest.mResult;
1242     }
1243 
setCdmaBroadcastActivation(boolean activate)1244     private boolean setCdmaBroadcastActivation(boolean activate) {
1245         if (DBG) {
1246             log("Calling setCdmaBroadcastActivation(" + activate + ")");
1247         }
1248 
1249         enforceNotOnHandlerThread("setCdmaBroadcastActivation");
1250         Request setRequest = new Request();
1251         synchronized (setRequest) {
1252             Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE,
1253                     setRequest);
1254 
1255             mPhone.mCi.setCdmaBroadcastActivation(activate, response);
1256 
1257             waitForResult(setRequest);
1258         }
1259 
1260         return (boolean) setRequest.mResult;
1261     }
1262 
1263     @UnsupportedAppUsage
log(String msg)1264     protected void log(String msg) {
1265         Rlog.d(LOG_TAG, msg);
1266     }
1267 
loge(String msg)1268     protected void loge(String msg) {
1269         Rlog.e(LOG_TAG, msg);
1270     }
1271 
loge(String msg, Throwable e)1272     protected void loge(String msg, Throwable e) {
1273         Rlog.e(LOG_TAG, msg, e);
1274     }
1275 
1276     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isImsSmsSupported()1277     public boolean isImsSmsSupported() {
1278         return mDispatchersController.isIms();
1279     }
1280 
1281     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getImsSmsFormat()1282     public String getImsSmsFormat() {
1283         return mDispatchersController.getImsSmsFormat();
1284     }
1285 
1286     /**
1287      * @deprecated Use {@link #sendStoredText(String, String, Uri, String, PendingIntent,
1288      * PendingIntent)} instead
1289      */
1290     @Deprecated
1291     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
sendStoredText(String callingPkg, int callingUser, Uri messageUri, String scAddress, PendingIntent sentIntent, PendingIntent deliveryIntent)1292     public void sendStoredText(String callingPkg, int callingUser, Uri messageUri, String scAddress,
1293             PendingIntent sentIntent, PendingIntent deliveryIntent) {
1294         sendStoredText(callingPkg, callingUser, null, messageUri,
1295                 scAddress, sentIntent, deliveryIntent);
1296     }
1297 
sendStoredText(String callingPkg, int callingUser, String callingAttributionTag, Uri messageUri, String scAddress, PendingIntent sentIntent, PendingIntent deliveryIntent)1298     public void sendStoredText(String callingPkg, int callingUser, String callingAttributionTag,
1299             Uri messageUri, String scAddress, PendingIntent sentIntent,
1300             PendingIntent deliveryIntent) {
1301         if (!mSmsPermissions.checkCallingCanSendSms(callingPkg, callingAttributionTag,
1302                 "Sending SMS message")) {
1303             returnUnspecifiedFailure(sentIntent);
1304             return;
1305         }
1306         if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
1307             log("sendStoredText: scAddr=" + scAddress + " messageUri=" + messageUri
1308                     + " sentIntent=" + sentIntent + " deliveryIntent=" + deliveryIntent);
1309         }
1310         final ContentResolver resolver = mContext.getContentResolver();
1311         if (!isFailedOrDraft(resolver, messageUri)) {
1312             loge("sendStoredText: not FAILED or DRAFT message");
1313             returnUnspecifiedFailure(sentIntent);
1314             return;
1315         }
1316         final String[] textAndAddress = loadTextAndAddress(resolver, messageUri);
1317         if (textAndAddress == null) {
1318             loge("sendStoredText: can not load text");
1319             returnUnspecifiedFailure(sentIntent);
1320             return;
1321         }
1322         notifyIfOutgoingEmergencySms(textAndAddress[1]);
1323         textAndAddress[1] = filterDestAddress(textAndAddress[1]);
1324         mDispatchersController.sendText(textAndAddress[1], scAddress, textAndAddress[0],
1325                 sentIntent, deliveryIntent, messageUri, callingPkg, callingUser,
1326                 true /* persistMessageForNonDefaultSmsApp */, SMS_MESSAGE_PRIORITY_NOT_SPECIFIED,
1327                 false /* expectMore */, SMS_MESSAGE_PERIOD_NOT_SPECIFIED, false /* isForVvm */,
1328                 0L /* messageId */);
1329     }
1330 
1331     /**
1332      * @deprecated Use {@link #sendStoredMultipartText(String, String, Uri, String, List, List)}
1333      * instead
1334      */
1335     @Deprecated
1336     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
sendStoredMultipartText(String callingPkg, int callingUser, Uri messageUri, String scAddress, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents)1337     public void sendStoredMultipartText(String callingPkg, int callingUser,
1338             Uri messageUri, String scAddress, List<PendingIntent> sentIntents,
1339             List<PendingIntent> deliveryIntents) {
1340         sendStoredMultipartText(callingPkg, callingUser, null,
1341                 messageUri, scAddress, sentIntents, deliveryIntents);
1342     }
1343 
sendStoredMultipartText(String callingPkg, int callingUser, String callingAttributionTag, Uri messageUri, String scAddress, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents)1344     public void sendStoredMultipartText(String callingPkg, int callingUser,
1345             String callingAttributionTag, Uri messageUri, String scAddress,
1346             List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
1347         if (!mSmsPermissions.checkCallingCanSendSms(callingPkg, callingAttributionTag,
1348                 "Sending SMS message")) {
1349             returnUnspecifiedFailure(sentIntents);
1350             return;
1351         }
1352         final ContentResolver resolver = mContext.getContentResolver();
1353         if (!isFailedOrDraft(resolver, messageUri)) {
1354             loge("sendStoredMultipartText: not FAILED or DRAFT message");
1355             returnUnspecifiedFailure(sentIntents);
1356             return;
1357         }
1358         final String[] textAndAddress = loadTextAndAddress(resolver, messageUri);
1359         if (textAndAddress == null) {
1360             loge("sendStoredMultipartText: can not load text");
1361             returnUnspecifiedFailure(sentIntents);
1362             return;
1363         }
1364         final ArrayList<String> parts = SmsManager.getDefault().divideMessage(textAndAddress[0]);
1365         if (parts == null || parts.size() < 1) {
1366             loge("sendStoredMultipartText: can not divide text");
1367             returnUnspecifiedFailure(sentIntents);
1368             return;
1369         }
1370         notifyIfOutgoingEmergencySms(textAndAddress[1]);
1371         textAndAddress[1] = filterDestAddress(textAndAddress[1]);
1372 
1373         if (parts.size() > 1 && parts.size() < 10 && !SmsMessage.hasEmsSupport()) {
1374             for (int i = 0; i < parts.size(); i++) {
1375                 // If EMS is not supported, we have to break down EMS into single segment SMS
1376                 // and add page info " x/y".
1377                 String singlePart = parts.get(i);
1378                 if (SmsMessage.shouldAppendPageNumberAsPrefix()) {
1379                     singlePart = String.valueOf(i + 1) + '/' + parts.size() + ' ' + singlePart;
1380                 } else {
1381                     singlePart = singlePart.concat(' ' + String.valueOf(i + 1) + '/'
1382                             + parts.size());
1383                 }
1384 
1385                 PendingIntent singleSentIntent = null;
1386                 if (sentIntents != null && sentIntents.size() > i) {
1387                     singleSentIntent = sentIntents.get(i);
1388                 }
1389 
1390                 PendingIntent singleDeliveryIntent = null;
1391                 if (deliveryIntents != null && deliveryIntents.size() > i) {
1392                     singleDeliveryIntent = deliveryIntents.get(i);
1393                 }
1394 
1395                 mDispatchersController.sendText(textAndAddress[1], scAddress, singlePart,
1396                         singleSentIntent, singleDeliveryIntent, messageUri, callingPkg,
1397                         callingUser, true  /* persistMessageForNonDefaultSmsApp */,
1398                         SMS_MESSAGE_PRIORITY_NOT_SPECIFIED,
1399                         false /* expectMore */, SMS_MESSAGE_PERIOD_NOT_SPECIFIED,
1400                         false /* isForVvm */, 0L /* messageId */);
1401             }
1402             return;
1403         }
1404 
1405         mDispatchersController.sendMultipartText(
1406                 textAndAddress[1], // destAddress
1407                 scAddress,
1408                 parts,
1409                 (ArrayList<PendingIntent>) sentIntents,
1410                 (ArrayList<PendingIntent>) deliveryIntents,
1411                 messageUri,
1412                 callingPkg, callingUser,
1413                 true  /* persistMessageForNonDefaultSmsApp */,
1414                 SMS_MESSAGE_PRIORITY_NOT_SPECIFIED,
1415                 false /* expectMore */,
1416                 SMS_MESSAGE_PERIOD_NOT_SPECIFIED,
1417                 0L /* messageId */);
1418     }
1419 
getSmsCapacityOnIcc(String callingPackage, String callingFeatureId)1420     public int getSmsCapacityOnIcc(String callingPackage, String callingFeatureId) {
1421         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
1422                 mContext, mPhone.getSubId(), callingPackage, callingFeatureId,
1423                 "getSmsCapacityOnIcc")) {
1424             return 0;
1425         }
1426 
1427         int numberOnIcc = 0;
1428         if (mPhone.getIccRecordsLoaded()) {
1429             final UiccProfile uiccProfile = UiccController.getInstance()
1430                     .getUiccProfileForPhone(mPhone.getPhoneId());
1431             if(uiccProfile != null) {
1432                 numberOnIcc = uiccProfile.getIccRecords().getSmsCapacityOnIcc();
1433             } else {
1434                 loge("uiccProfile is null");
1435             }
1436         } else {
1437             loge("getSmsCapacityOnIcc - aborting, no icc card present.");
1438         }
1439 
1440         log("getSmsCapacityOnIcc().numberOnIcc = " + numberOnIcc);
1441         return numberOnIcc;
1442     }
1443 
isFailedOrDraft(ContentResolver resolver, Uri messageUri)1444     private boolean isFailedOrDraft(ContentResolver resolver, Uri messageUri) {
1445         // Clear the calling identity and query the database using the phone user id
1446         // Otherwise the AppOps check in TelephonyProvider would complain about mismatch
1447         // between the calling uid and the package uid
1448         final long identity = Binder.clearCallingIdentity();
1449         Cursor cursor = null;
1450         try {
1451             cursor = resolver.query(
1452                     messageUri,
1453                     new String[]{ Telephony.Sms.TYPE },
1454                     null/*selection*/,
1455                     null/*selectionArgs*/,
1456                     null/*sortOrder*/);
1457             if (cursor != null && cursor.moveToFirst()) {
1458                 final int type = cursor.getInt(0);
1459                 return type == Telephony.Sms.MESSAGE_TYPE_DRAFT
1460                         || type == Telephony.Sms.MESSAGE_TYPE_FAILED;
1461             }
1462         } catch (SQLiteException e) {
1463             loge("isFailedOrDraft: query message type failed", e);
1464         } finally {
1465             if (cursor != null) {
1466                 cursor.close();
1467             }
1468             Binder.restoreCallingIdentity(identity);
1469         }
1470         return false;
1471     }
1472 
1473     // Return an array including both the SMS text (0) and address (1)
loadTextAndAddress(ContentResolver resolver, Uri messageUri)1474     private String[] loadTextAndAddress(ContentResolver resolver, Uri messageUri) {
1475         // Clear the calling identity and query the database using the phone user id
1476         // Otherwise the AppOps check in TelephonyProvider would complain about mismatch
1477         // between the calling uid and the package uid
1478         final long identity = Binder.clearCallingIdentity();
1479         Cursor cursor = null;
1480         try {
1481             cursor = resolver.query(
1482                     messageUri,
1483                     new String[]{
1484                             Telephony.Sms.BODY,
1485                             Telephony.Sms.ADDRESS
1486                     },
1487                     null/*selection*/,
1488                     null/*selectionArgs*/,
1489                     null/*sortOrder*/);
1490             if (cursor != null && cursor.moveToFirst()) {
1491                 return new String[]{ cursor.getString(0), cursor.getString(1) };
1492             }
1493         } catch (SQLiteException e) {
1494             loge("loadText: query message text failed", e);
1495         } finally {
1496             if (cursor != null) {
1497                 cursor.close();
1498             }
1499             Binder.restoreCallingIdentity(identity);
1500         }
1501         return null;
1502     }
1503 
1504     @VisibleForTesting
notifyIfOutgoingEmergencySms(String destAddr)1505     public void notifyIfOutgoingEmergencySms(String destAddr) {
1506         Phone[] allPhones = mPhoneFactoryProxy.getPhones();
1507         EmergencyNumber emergencyNumber = getEmergencyNumber(mPhone, destAddr);
1508         if (emergencyNumber != null) {
1509             mPhone.notifyOutgoingEmergencySms(emergencyNumber);
1510         } else if (allPhones.length > 1) {
1511             // If there are multiple active SIMs, check all instances:
1512             for (Phone phone : allPhones) {
1513                 // If the current iteration was already checked, skip:
1514                 if (phone.getPhoneId() == mPhone.getPhoneId()) {
1515                     continue;
1516                 }
1517                 emergencyNumber = getEmergencyNumber(phone, destAddr);
1518                 if (emergencyNumber != null) {
1519                     mPhone.notifyOutgoingEmergencySms(emergencyNumber);
1520                     break;
1521                 }
1522             }
1523         }
1524     }
1525 
getEmergencyNumber(Phone phone, String number)1526     private EmergencyNumber getEmergencyNumber(Phone phone, String number) {
1527         if (!phone.hasCalling()) return null;
1528         EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
1529         if (tracker == null) return null;
1530         return tracker.getEmergencyNumber(number);
1531     }
1532 
returnUnspecifiedFailure(PendingIntent pi)1533     private void returnUnspecifiedFailure(PendingIntent pi) {
1534         if (pi != null) {
1535             try {
1536                 pi.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE);
1537             } catch (PendingIntent.CanceledException e) {
1538                 // ignore
1539             }
1540         }
1541     }
1542 
returnUnspecifiedFailure(List<PendingIntent> pis)1543     private void returnUnspecifiedFailure(List<PendingIntent> pis) {
1544         if (pis == null) {
1545             return;
1546         }
1547         for (PendingIntent pi : pis) {
1548             returnUnspecifiedFailure(pi);
1549         }
1550     }
1551 
1552     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
filterDestAddress(String destAddr)1553     private String filterDestAddress(String destAddr) {
1554         String result = SmsNumberUtils.filterDestAddr(mContext, mPhone.getSubId(), destAddr);
1555         return result != null ? result : destAddr;
1556     }
1557 
waitForResult(Request request)1558     private void waitForResult(Request request) {
1559         synchronized (request) {
1560             while (!request.mStatus.get()) {
1561                 try {
1562                     request.wait();
1563                 } catch (InterruptedException e) {
1564                     log("Interrupted while waiting for result");
1565                 }
1566             }
1567         }
1568     }
1569 
1570     /**
1571      * Get InboundSmsHandler for the phone.
1572      */
getInboundSmsHandler(boolean is3gpp2)1573     public InboundSmsHandler getInboundSmsHandler(boolean is3gpp2) {
1574         return mDispatchersController.getInboundSmsHandler(is3gpp2);
1575     }
1576 
dump(FileDescriptor fd, PrintWriter pw, String[] args)1577     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1578         pw.println("Enabled GSM channels: " + mCellBroadcastRangeManager);
1579         pw.println("Enabled CDMA channels: " + mCdmaBroadcastRangeManager);
1580         pw.println("CellBroadcast log:");
1581         mCellBroadcastLocalLog.dump(fd, pw, args);
1582         pw.println("SMS dispatcher controller log:");
1583         mDispatchersController.dump(fd, pw, args);
1584         pw.flush();
1585     }
1586 }
1587