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