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.flags.FeatureFlags; 52 import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; 53 import com.android.internal.telephony.uicc.IccConstants; 54 import com.android.internal.telephony.uicc.IccFileHandler; 55 import com.android.internal.telephony.uicc.IccUtils; 56 import com.android.internal.telephony.uicc.UiccController; 57 import com.android.internal.telephony.uicc.UiccProfile; 58 import com.android.internal.util.HexDump; 59 import com.android.telephony.Rlog; 60 61 import java.io.FileDescriptor; 62 import java.io.PrintWriter; 63 import java.util.ArrayList; 64 import java.util.Arrays; 65 import java.util.List; 66 import java.util.concurrent.atomic.AtomicBoolean; 67 68 /** 69 * IccSmsInterfaceManager to provide an inter-process communication to 70 * access Sms in Icc. 71 */ 72 public class IccSmsInterfaceManager { 73 static final String LOG_TAG = "IccSmsInterfaceManager"; 74 static final boolean DBG = true; 75 76 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 77 private CellBroadcastRangeManager mCellBroadcastRangeManager = 78 new CellBroadcastRangeManager(); 79 private CdmaBroadcastRangeManager mCdmaBroadcastRangeManager = 80 new CdmaBroadcastRangeManager(); 81 82 private static final int EVENT_LOAD_DONE = 1; 83 private static final int EVENT_UPDATE_DONE = 2; 84 protected static final int EVENT_SET_BROADCAST_ACTIVATION_DONE = 3; 85 protected static final int EVENT_SET_BROADCAST_CONFIG_DONE = 4; 86 private static final int EVENT_GET_SMSC_DONE = 5; 87 private static final int EVENT_SET_SMSC_DONE = 6; 88 private static final int SMS_CB_CODE_SCHEME_MIN = 0; 89 private static final int SMS_CB_CODE_SCHEME_MAX = 255; 90 public static final int SMS_MESSAGE_PRIORITY_NOT_SPECIFIED = -1; 91 public static final int SMS_MESSAGE_PERIOD_NOT_SPECIFIED = -1; 92 93 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 94 protected Phone mPhone; 95 @UnsupportedAppUsage 96 final protected Context mContext; 97 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 98 final protected AppOpsManager mAppOps; 99 @VisibleForTesting 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, String callingAttributionTag, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm)410 public void sendDataWithSelfPermissions(String callingPackage, String callingAttributionTag, 411 String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, 412 PendingIntent deliveryIntent, boolean isForVvm) { 413 if (!mSmsPermissions.checkCallingOrSelfCanSendSms(callingPackage, callingAttributionTag, 414 "Sending SMS message")) { 415 returnUnspecifiedFailure(sentIntent); 416 return; 417 } 418 sendDataInternal(callingPackage, 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, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)428 public void sendData(String callingPackage, String destAddr, String scAddr, int destPort, 429 byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 430 sendData(callingPackage, 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, String callingAttributionTag, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)438 public void sendData(String callingPackage, 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, 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, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm)477 private void sendDataInternal(String callingPackage, String destAddr, String scAddr, 478 int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, 479 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, destAddr, scAddr, destPort, data, 487 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, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp, long messageId, boolean skipShortCodeCheck)495 public void sendText(String callingPackage, String destAddr, String scAddr, 496 String text, PendingIntent sentIntent, PendingIntent deliveryIntent, 497 boolean persistMessageForNonDefaultSmsApp, long messageId, boolean skipShortCodeCheck) { 498 sendTextInternal(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent, 499 persistMessageForNonDefaultSmsApp, SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, 500 false /* expectMore */, SMS_MESSAGE_PERIOD_NOT_SPECIFIED, false /* isForVvm */, 501 messageId, skipShortCodeCheck); 502 } 503 504 /** 505 * A permissions check before passing to {@link IccSmsInterfaceManager#sendTextInternal}. 506 * This method checks if the calling package or itself has the permission to send the sms. 507 */ sendTextWithSelfPermissions(String callingPackage, String callingAttributeTag, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage, boolean isForVvm)508 public void sendTextWithSelfPermissions(String callingPackage, String callingAttributeTag, 509 String destAddr, String scAddr, String text, PendingIntent sentIntent, 510 PendingIntent deliveryIntent, boolean persistMessage, boolean isForVvm) { 511 if (!mSmsPermissions.checkCallingOrSelfCanSendSms(callingPackage, callingAttributeTag, 512 "Sending SMS message")) { 513 returnUnspecifiedFailure(sentIntent); 514 return; 515 } 516 sendTextInternal(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent, 517 persistMessage, SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, false /* expectMore */, 518 SMS_MESSAGE_PERIOD_NOT_SPECIFIED, isForVvm, 0L /* messageId */); 519 } 520 521 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)522 private void sendTextInternal(String callingPackage, String destAddr, String scAddr, 523 String text, PendingIntent sentIntent, PendingIntent deliveryIntent, 524 boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore, 525 int validityPeriod, boolean isForVvm, long messageId) { 526 sendTextInternal(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent, 527 persistMessageForNonDefaultSmsApp, priority, expectMore, validityPeriod, isForVvm, 528 messageId, false); 529 } 530 531 /** 532 * Send a text based SMS. 533 * 534 * @param destAddr the address to send the message to 535 * @param scAddr is the service center address or null to use 536 * the current default SMSC 537 * @param text the body of the message to send 538 * @param sentIntent if not NULL this <code>PendingIntent</code> is 539 * broadcast when the message is successfully sent, or failed. 540 * The result code will be <code>Activity.RESULT_OK<code> for success, 541 * or one of these errors:<br> 542 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 543 * <code>RESULT_ERROR_RADIO_OFF</code><br> 544 * <code>RESULT_ERROR_NULL_PDU</code><br> 545 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 546 * the extra "errorCode" containing a radio technology specific value, 547 * generally only useful for troubleshooting.<br> 548 * The per-application based SMS control checks sentIntent. If sentIntent 549 * is NULL the caller will be checked against all unknown applications, 550 * which cause smaller number of SMS to be sent in checking period. 551 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 552 * broadcast when the message is delivered to the recipient. The 553 * raw pdu of the status report is in the extended data ("pdu"). 554 * @param persistMessageForNonDefaultSmsApp whether the sent message should 555 * be automatically persisted in the SMS db. It only affects messages sent 556 * by a non-default SMS app. Currently only the carrier app can set this 557 * parameter to false to skip auto message persistence. 558 * @param priority Priority level of the message 559 * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 560 * --------------------------------- 561 * PRIORITY | Level of Priority 562 * --------------------------------- 563 * '00' | Normal 564 * '01' | Interactive 565 * '10' | Urgent 566 * '11' | Emergency 567 * ---------------------------------- 568 * Any Other values including negative considered as Invalid Priority Indicator of the message. 569 * @param expectMore is a boolean to indicate the sending messages through same link or not. 570 * @param validityPeriod Validity Period of the message in mins. 571 * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. 572 * Validity Period(Minimum) -> 5 mins 573 * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). 574 * Any Other values including negative considered as Invalid Validity Period of the message. 575 * @param messageId An id that uniquely identifies the message requested to be sent. 576 * Used for logging and diagnostics purposes. The id may be 0. 577 * @param skipShortCodeCheck Skip check for short code type destination address. 578 */ 579 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)580 private void sendTextInternal(String callingPackage, String destAddr, String scAddr, 581 String text, PendingIntent sentIntent, PendingIntent deliveryIntent, 582 boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore, 583 int validityPeriod, boolean isForVvm, long messageId, boolean skipShortCodeCheck) { 584 if (Rlog.isLoggable("SMS", Log.VERBOSE)) { 585 log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr 586 + " text='" + text + "' sentIntent=" + sentIntent + " deliveryIntent=" 587 + deliveryIntent + " priority=" + priority + " expectMore=" + expectMore 588 + " validityPeriod=" + validityPeriod + " isForVVM=" + isForVvm 589 + " " + SmsController.formatCrossStackMessageId(messageId)); 590 } 591 notifyIfOutgoingEmergencySms(destAddr); 592 destAddr = filterDestAddress(destAddr); 593 mDispatchersController.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent, 594 null/*messageUri*/, callingPackage, persistMessageForNonDefaultSmsApp, 595 priority, expectMore, validityPeriod, isForVvm, messageId, skipShortCodeCheck); 596 } 597 598 /** 599 * Send a text based SMS with Messaging Options. 600 * 601 * @param destAddr the address to send the message to 602 * @param scAddr is the service center address or null to use 603 * the current default SMSC 604 * @param text the body of the message to send 605 * @param sentIntent if not NULL this <code>PendingIntent</code> is 606 * broadcast when the message is successfully sent, or failed. 607 * The result code will be <code>Activity.RESULT_OK<code> for success, 608 * or one of these errors:<br> 609 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 610 * <code>RESULT_ERROR_RADIO_OFF</code><br> 611 * <code>RESULT_ERROR_NULL_PDU</code><br> 612 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 613 * the extra "errorCode" containing a radio technology specific value, 614 * generally only useful for troubleshooting.<br> 615 * The per-application based SMS control checks sentIntent. If sentIntent 616 * is NULL the caller will be checked against all unknown applications, 617 * which cause smaller number of SMS to be sent in checking period. 618 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 619 * broadcast when the message is delivered to the recipient. The 620 * raw pdu of the status report is in the extended data ("pdu"). 621 * @param persistMessageForNonDefaultSmsApp whether the sent message should 622 * be automatically persisted in the SMS db. It only affects messages sent 623 * by a non-default SMS app. Currently only the carrier app can set this 624 * parameter to false to skip auto message persistence. 625 * @param priority Priority level of the message 626 * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 627 * --------------------------------- 628 * PRIORITY | Level of Priority 629 * --------------------------------- 630 * '00' | Normal 631 * '01' | Interactive 632 * '10' | Urgent 633 * '11' | Emergency 634 * ---------------------------------- 635 * Any Other values including negative considered as Invalid Priority Indicator of the message. 636 * @param expectMore is a boolean to indicate the sending messages through same link or not. 637 * @param validityPeriod Validity Period of the message in mins. 638 * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. 639 * Validity Period(Minimum) -> 5 mins 640 * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). 641 * Any Other values including negative considered as Invalid Validity Period of the message. 642 */ 643 sendTextWithOptions(String callingPackage, String callingAttributionTag, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore, int validityPeriod)644 public void sendTextWithOptions(String callingPackage, String callingAttributionTag, 645 String destAddr, String scAddr, String text, PendingIntent sentIntent, 646 PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp, int priority, 647 boolean expectMore, int validityPeriod) { 648 if (!mSmsPermissions.checkCallingCanSendText(persistMessageForNonDefaultSmsApp, 649 callingPackage, callingAttributionTag, "Sending SMS message")) { 650 returnUnspecifiedFailure(sentIntent); 651 return; 652 } 653 sendTextInternal(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent, 654 persistMessageForNonDefaultSmsApp, priority, expectMore, validityPeriod, 655 false /* isForVvm */, 0L /* messageId */); 656 } 657 658 /** 659 * Inject an SMS PDU into the android application framework. 660 * 661 * @param pdu is the byte array of pdu to be injected into android application framework 662 * @param format is the format of SMS pdu (3gpp or 3gpp2) 663 * @param receivedIntent if not NULL this <code>PendingIntent</code> is 664 * broadcast when the message is successfully received by the 665 * android application framework. This intent is broadcasted at 666 * the same time an SMS received from radio is acknowledged back. 667 */ 668 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent)669 public void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) { 670 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) 671 != PackageManager.PERMISSION_GRANTED) { 672 mSmsPermissions.enforceCallerIsImsAppOrCarrierApp("injectSmsPdu"); 673 } 674 675 if (Rlog.isLoggable("SMS", Log.VERBOSE)) { 676 log("pdu: " + IccUtils.bytesToHexString(pdu) 677 + "\n format=" + format 678 + "\n receivedIntent=" + receivedIntent); 679 } 680 mDispatchersController.injectSmsPdu(pdu, format, false /* isOverIms */, 681 result -> { 682 if (receivedIntent != null) { 683 try { 684 receivedIntent.send(result); 685 } catch (PendingIntent.CanceledException e) { 686 loge("receivedIntent cancelled."); 687 } 688 } 689 } 690 ); 691 } 692 693 /** 694 * Send a multi-part text based SMS. 695 * 696 * @param destAddr the address to send the message to 697 * @param scAddr is the service center address or null to use 698 * the current default SMSC 699 * @param parts an <code>ArrayList</code> of strings that, in order, 700 * comprise the original message 701 * @param sentIntents if not null, an <code>ArrayList</code> of 702 * <code>PendingIntent</code>s (one for each message part) that is 703 * broadcast when the corresponding message part has been sent. 704 * The result code will be <code>Activity.RESULT_OK<code> for success, 705 * or one of these errors: 706 * <code>RESULT_ERROR_GENERIC_FAILURE</code> 707 * <code>RESULT_ERROR_RADIO_OFF</code> 708 * <code>RESULT_ERROR_NULL_PDU</code>. 709 * The per-application based SMS control checks sentIntent. If sentIntent 710 * is NULL the caller will be checked against all unknown applications, 711 * which cause smaller number of SMS to be sent in checking period. 712 * @param deliveryIntents if not null, an <code>ArrayList</code> of 713 * <code>PendingIntent</code>s (one for each message part) that is 714 * broadcast when the corresponding message part has been delivered 715 * to the recipient. The raw pdu of the status report is in the 716 * extended data ("pdu"). 717 * @param messageId An id that uniquely identifies the message requested to be sent. 718 * Used for logging and diagnostics purposes. The id may be 0. 719 */ 720 sendMultipartText(String callingPackage, String callingAttributionTag, String destAddr, String scAddr, List<String> parts, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp, long messageId)721 public void sendMultipartText(String callingPackage, String callingAttributionTag, 722 String destAddr, String scAddr, List<String> parts, List<PendingIntent> sentIntents, 723 List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp, 724 long messageId) { 725 sendMultipartTextWithOptions(callingPackage, callingAttributionTag, destAddr, scAddr, parts, 726 sentIntents, deliveryIntents, persistMessageForNonDefaultSmsApp, 727 SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, false /* expectMore */, 728 SMS_MESSAGE_PERIOD_NOT_SPECIFIED, 729 messageId); 730 } 731 732 /** 733 * Send a multi-part text based SMS with Messaging Options. 734 * 735 * @param destAddr the address to send the message to 736 * @param scAddr is the service center address or null to use 737 * the current default SMSC 738 * @param parts an <code>ArrayList</code> of strings that, in order, 739 * comprise the original message 740 * @param sentIntents if not null, an <code>ArrayList</code> of 741 * <code>PendingIntent</code>s (one for each message part) that is 742 * broadcast when the corresponding message part has been sent. 743 * The result code will be <code>Activity.RESULT_OK<code> for success, 744 * or one of these errors: 745 * <code>RESULT_ERROR_GENERIC_FAILURE</code> 746 * <code>RESULT_ERROR_RADIO_OFF</code> 747 * <code>RESULT_ERROR_NULL_PDU</code>. 748 * The per-application based SMS control checks sentIntent. If sentIntent 749 * is NULL the caller will be checked against all unknown applications, 750 * which cause smaller number of SMS to be sent in checking period. 751 * @param deliveryIntents if not null, an <code>ArrayList</code> of 752 * <code>PendingIntent</code>s (one for each message part) that is 753 * broadcast when the corresponding message part has been delivered 754 * to the recipient. The raw pdu of the status report is in the 755 * extended data ("pdu"). 756 * @param persistMessageForNonDefaultSmsApp whether the sent message should 757 * be automatically persisted in the SMS db. It only affects messages sent 758 * by a non-default SMS app. Currently only the carrier app can set this 759 * parameter to false to skip auto message persistence. 760 * @param priority Priority level of the message 761 * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 762 * --------------------------------- 763 * PRIORITY | Level of Priority 764 * --------------------------------- 765 * '00' | Normal 766 * '01' | Interactive 767 * '10' | Urgent 768 * '11' | Emergency 769 * ---------------------------------- 770 * Any Other values including negative considered as Invalid Priority Indicator of the message. 771 * @param expectMore is a boolean to indicate the sending messages through same link or not. 772 * @param validityPeriod Validity Period of the message in mins. 773 * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. 774 * Validity Period(Minimum) -> 5 mins 775 * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). 776 * Any Other values including negative considered as Invalid Validity Period of the message. 777 * @param messageId An id that uniquely identifies the message requested to be sent. 778 * Used for logging and diagnostics purposes. The id may be 0. 779 */ 780 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)781 public void sendMultipartTextWithOptions(String callingPackage, String callingAttributionTag, 782 String destAddr, String scAddr, List<String> parts, List<PendingIntent> sentIntents, 783 List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp, 784 int priority, boolean expectMore, int validityPeriod, long messageId) { 785 if (!mSmsPermissions.checkCallingCanSendText(persistMessageForNonDefaultSmsApp, 786 callingPackage, callingAttributionTag, "Sending SMS message")) { 787 returnUnspecifiedFailure(sentIntents); 788 return; 789 } 790 if (Rlog.isLoggable("SMS", Log.VERBOSE)) { 791 int i = 0; 792 for (String part : parts) { 793 log("sendMultipartTextWithOptions: destAddr=" + destAddr + ", srAddr=" + scAddr 794 + ", part[" + (i++) + "]=" + part 795 + " " + SmsController.formatCrossStackMessageId(messageId)); 796 } 797 } 798 notifyIfOutgoingEmergencySms(destAddr); 799 destAddr = filterDestAddress(destAddr); 800 801 if (parts.size() > 1 && parts.size() < 10 && !SmsMessage.hasEmsSupport()) { 802 for (int i = 0; i < parts.size(); i++) { 803 // If EMS is not supported, we have to break down EMS into single segment SMS 804 // and add page info " x/y". 805 String singlePart = parts.get(i); 806 if (SmsMessage.shouldAppendPageNumberAsPrefix()) { 807 singlePart = String.valueOf(i + 1) + '/' + parts.size() + ' ' + singlePart; 808 } else { 809 singlePart = singlePart.concat(' ' + String.valueOf(i + 1) + '/' 810 + parts.size()); 811 } 812 813 PendingIntent singleSentIntent = null; 814 if (sentIntents != null && sentIntents.size() > i) { 815 singleSentIntent = sentIntents.get(i); 816 } 817 818 PendingIntent singleDeliveryIntent = null; 819 if (deliveryIntents != null && deliveryIntents.size() > i) { 820 singleDeliveryIntent = deliveryIntents.get(i); 821 } 822 823 mDispatchersController.sendText(destAddr, scAddr, singlePart, singleSentIntent, 824 singleDeliveryIntent, null /* messageUri */, callingPackage, 825 persistMessageForNonDefaultSmsApp, priority, expectMore, validityPeriod, 826 false /* isForVvm */, messageId); 827 } 828 return; 829 } 830 831 mDispatchersController.sendMultipartText(destAddr, 832 scAddr, 833 (ArrayList<String>) parts, 834 (ArrayList<PendingIntent>) sentIntents, 835 (ArrayList<PendingIntent>) deliveryIntents, 836 null, callingPackage, persistMessageForNonDefaultSmsApp, 837 priority, expectMore, validityPeriod, messageId); 838 839 } 840 841 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getPremiumSmsPermission(String packageName)842 public int getPremiumSmsPermission(String packageName) { 843 return mDispatchersController.getPremiumSmsPermission(packageName); 844 } 845 846 847 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setPremiumSmsPermission(String packageName, int permission)848 public void setPremiumSmsPermission(String packageName, int permission) { 849 mDispatchersController.setPremiumSmsPermission(packageName, permission); 850 } 851 852 /** 853 * create SmsRawData lists from all sms record byte[] 854 * Use null to indicate "free" record 855 * 856 * @param messages List of message records from EF_SMS. 857 * @return SmsRawData list of all in-used records 858 */ buildValidRawData(ArrayList<byte[]> messages)859 protected ArrayList<SmsRawData> buildValidRawData(ArrayList<byte[]> messages) { 860 int count = messages.size(); 861 ArrayList<SmsRawData> ret; 862 863 ret = new ArrayList<SmsRawData>(count); 864 865 for (int i = 0; i < count; i++) { 866 byte[] ba = messages.get(i); 867 if ((ba[0] & 0x01) == STATUS_ON_ICC_FREE) { 868 ret.add(null); 869 } else { 870 ret.add(new SmsRawData(messages.get(i))); 871 } 872 } 873 874 return ret; 875 } 876 877 /** 878 * Generates an EF_SMS record from status and raw PDU. 879 * 880 * @param status Message status. See TS 51.011 10.5.3. 881 * @param pdu Raw message PDU. 882 * @return byte array for the record. 883 */ makeSmsRecordData(int status, byte[] pdu)884 protected byte[] makeSmsRecordData(int status, byte[] pdu) { 885 byte[] data; 886 if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) { 887 data = new byte[SmsManager.SMS_RECORD_LENGTH]; 888 } else { 889 data = new byte[SmsManager.CDMA_SMS_RECORD_LENGTH]; 890 } 891 892 // Status bits for this record. See TS 51.011 10.5.3 893 data[0] = (byte) (status & 0x07); 894 895 System.arraycopy(pdu, 0, data, 1, pdu.length); 896 897 // Pad out with 0xFF's. 898 for (int j = pdu.length+1; j < data.length; j++) { 899 data[j] = -1; 900 } 901 902 return data; 903 } 904 905 /** 906 * Gets the SMSC address from (U)SIM. 907 * 908 * @return the SMSC address string, null if failed. 909 */ getSmscAddressFromIccEf(String callingPackage)910 public String getSmscAddressFromIccEf(String callingPackage) { 911 if (!mSmsPermissions.checkCallingOrSelfCanGetSmscAddress( 912 callingPackage, "getSmscAddressFromIccEf")) { 913 loge("Caller do not have permission to call GetSmscAddress"); 914 return null; 915 } 916 enforceNotOnHandlerThread("getSmscAddressFromIccEf"); 917 Request getRequest = new Request(); 918 synchronized (getRequest) { 919 Message response = mHandler.obtainMessage(EVENT_GET_SMSC_DONE, getRequest); 920 mPhone.mCi.getSmscAddress(response); 921 waitForResult(getRequest); 922 } 923 return (String) getRequest.mResult; 924 } 925 926 /** 927 * Sets the SMSC address on (U)SIM. 928 * 929 * @param smsc the SMSC address string. 930 * @return true for success, false otherwise. 931 */ setSmscAddressOnIccEf(String callingPackage, String smsc)932 public boolean setSmscAddressOnIccEf(String callingPackage, String smsc) { 933 if (!mSmsPermissions.checkCallingOrSelfCanSetSmscAddress( 934 callingPackage, "setSmscAddressOnIccEf")) { 935 loge("Caller do not have permission to call SetSmscAddress"); 936 return false; 937 } 938 enforceNotOnHandlerThread("setSmscAddressOnIccEf"); 939 Request setRequest = new Request(); 940 synchronized (setRequest) { 941 Message response = mHandler.obtainMessage(EVENT_SET_SMSC_DONE, setRequest); 942 mPhone.mCi.setSmscAddress(smsc, response); 943 waitForResult(setRequest); 944 } 945 return (boolean) setRequest.mResult; 946 } 947 enableCellBroadcast(int messageIdentifier, int ranType)948 public boolean enableCellBroadcast(int messageIdentifier, int ranType) { 949 return enableCellBroadcastRange(messageIdentifier, messageIdentifier, ranType); 950 } 951 disableCellBroadcast(int messageIdentifier, int ranType)952 public boolean disableCellBroadcast(int messageIdentifier, int ranType) { 953 return disableCellBroadcastRange(messageIdentifier, messageIdentifier, ranType); 954 } 955 enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType)956 public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) { 957 mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, 958 "enabling cell broadcast range [" + startMessageId + "-" + endMessageId + "]. " 959 + "ranType=" + ranType); 960 if (ranType == SmsCbMessage.MESSAGE_FORMAT_3GPP) { 961 return enableGsmBroadcastRange(startMessageId, endMessageId); 962 } else if (ranType == SmsCbMessage.MESSAGE_FORMAT_3GPP2) { 963 return enableCdmaBroadcastRange(startMessageId, endMessageId); 964 } else { 965 throw new IllegalArgumentException("Not a supported RAN Type"); 966 } 967 } 968 disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType)969 public boolean disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) { 970 mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, 971 "disabling cell broadcast range [" + startMessageId + "-" + endMessageId 972 + "]. ranType=" + ranType); 973 if (ranType == SmsCbMessage.MESSAGE_FORMAT_3GPP) { 974 return disableGsmBroadcastRange(startMessageId, endMessageId); 975 } else if (ranType == SmsCbMessage.MESSAGE_FORMAT_3GPP2) { 976 return disableCdmaBroadcastRange(startMessageId, endMessageId); 977 } else { 978 throw new IllegalArgumentException("Not a supported RAN Type"); 979 } 980 } 981 982 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) enableGsmBroadcastRange(int startMessageId, int endMessageId)983 synchronized public boolean enableGsmBroadcastRange(int startMessageId, int endMessageId) { 984 985 mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, 986 "Enabling cell broadcast SMS"); 987 988 String client = mContext.getPackageManager().getNameForUid( 989 Binder.getCallingUid()); 990 991 String msg; 992 if (!mCellBroadcastRangeManager.enableRange(startMessageId, endMessageId, client)) { 993 msg = "Failed to add GSM cell broadcast channels range " + startMessageId 994 + " to " + endMessageId; 995 log(msg); 996 mCellBroadcastLocalLog.log(msg); 997 return false; 998 } 999 1000 if (DBG) { 1001 msg = "Added GSM cell broadcast channels range " + startMessageId 1002 + " to " + endMessageId; 1003 log(msg); 1004 mCellBroadcastLocalLog.log(msg); 1005 } 1006 1007 setCellBroadcastActivation(!mCellBroadcastRangeManager.isEmpty()); 1008 1009 return true; 1010 } 1011 1012 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) disableGsmBroadcastRange(int startMessageId, int endMessageId)1013 synchronized public boolean disableGsmBroadcastRange(int startMessageId, int endMessageId) { 1014 1015 mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, 1016 "Disabling cell broadcast SMS"); 1017 1018 String client = mContext.getPackageManager().getNameForUid( 1019 Binder.getCallingUid()); 1020 1021 String msg; 1022 if (!mCellBroadcastRangeManager.disableRange(startMessageId, endMessageId, client)) { 1023 msg = "Failed to remove GSM cell broadcast channels range " + startMessageId 1024 + " to " + endMessageId; 1025 log(msg); 1026 mCellBroadcastLocalLog.log(msg); 1027 return false; 1028 } 1029 1030 if (DBG) { 1031 msg = "Removed GSM cell broadcast channels range " + startMessageId 1032 + " to " + endMessageId; 1033 log(msg); 1034 mCellBroadcastLocalLog.log(msg); 1035 } 1036 1037 setCellBroadcastActivation(!mCellBroadcastRangeManager.isEmpty()); 1038 1039 return true; 1040 } 1041 1042 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) enableCdmaBroadcastRange(int startMessageId, int endMessageId)1043 synchronized public boolean enableCdmaBroadcastRange(int startMessageId, int endMessageId) { 1044 1045 mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, 1046 "Enabling cdma broadcast SMS"); 1047 1048 String client = mContext.getPackageManager().getNameForUid( 1049 Binder.getCallingUid()); 1050 1051 String msg; 1052 if (!mCdmaBroadcastRangeManager.enableRange(startMessageId, endMessageId, client)) { 1053 msg = "Failed to add cdma broadcast channels range " + startMessageId + " to " 1054 + endMessageId; 1055 log(msg); 1056 mCellBroadcastLocalLog.log(msg); 1057 return false; 1058 } 1059 1060 if (DBG) { 1061 msg = "Added cdma broadcast channels range " + startMessageId + " to " + endMessageId; 1062 log(msg); 1063 mCellBroadcastLocalLog.log(msg); 1064 } 1065 1066 setCdmaBroadcastActivation(!mCdmaBroadcastRangeManager.isEmpty()); 1067 1068 return true; 1069 } 1070 1071 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) disableCdmaBroadcastRange(int startMessageId, int endMessageId)1072 synchronized public boolean disableCdmaBroadcastRange(int startMessageId, int endMessageId) { 1073 1074 mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, 1075 "Disabling cell broadcast SMS"); 1076 1077 String client = mContext.getPackageManager().getNameForUid( 1078 Binder.getCallingUid()); 1079 1080 String msg; 1081 if (!mCdmaBroadcastRangeManager.disableRange(startMessageId, endMessageId, client)) { 1082 msg = "Failed to remove cdma broadcast channels range " + startMessageId + " to " 1083 + endMessageId; 1084 log(msg); 1085 mCellBroadcastLocalLog.log(msg); 1086 return false; 1087 } 1088 1089 if (DBG) { 1090 msg = "Removed cdma broadcast channels range " + startMessageId + " to " + endMessageId; 1091 log(msg); 1092 mCellBroadcastLocalLog.log(msg); 1093 } 1094 1095 setCdmaBroadcastActivation(!mCdmaBroadcastRangeManager.isEmpty()); 1096 1097 return true; 1098 } 1099 1100 /** 1101 * Reset all cell broadcast ranges. Previously enabled ranges will become invalid after this. 1102 */ 1103 @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS) resetAllCellBroadcastRanges()1104 public void resetAllCellBroadcastRanges() { 1105 mContext.enforceCallingPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS, 1106 "resetAllCellBroadcastRanges"); 1107 mCdmaBroadcastRangeManager.clearRanges(); 1108 mCellBroadcastRangeManager.clearRanges(); 1109 log("Cell broadcast ranges reset."); 1110 } 1111 1112 class CellBroadcastRangeManager extends IntRangeManager { 1113 private ArrayList<SmsBroadcastConfigInfo> mConfigList = 1114 new ArrayList<SmsBroadcastConfigInfo>(); 1115 1116 /** 1117 * Called when the list of enabled ranges has changed. This will be 1118 * followed by zero or more calls to {@link #addRange} followed by 1119 * a call to {@link #finishUpdate}. 1120 */ startUpdate()1121 protected void startUpdate() { 1122 mConfigList.clear(); 1123 } 1124 1125 /** 1126 * Called after {@link #startUpdate} to indicate a range of enabled 1127 * values. 1128 * @param startId the first id included in the range 1129 * @param endId the last id included in the range 1130 */ addRange(int startId, int endId, boolean selected)1131 protected void addRange(int startId, int endId, boolean selected) { 1132 mConfigList.add(new SmsBroadcastConfigInfo(startId, endId, 1133 SMS_CB_CODE_SCHEME_MIN, SMS_CB_CODE_SCHEME_MAX, selected)); 1134 } 1135 1136 /** 1137 * Called to indicate the end of a range update started by the 1138 * previous call to {@link #startUpdate}. 1139 * @return true if successful, false otherwise 1140 */ finishUpdate()1141 protected boolean finishUpdate() { 1142 if (mConfigList.isEmpty()) { 1143 return true; 1144 } else { 1145 SmsBroadcastConfigInfo[] configs = 1146 mConfigList.toArray(new SmsBroadcastConfigInfo[mConfigList.size()]); 1147 return setCellBroadcastConfig(configs); 1148 } 1149 } 1150 } 1151 1152 class CdmaBroadcastRangeManager extends IntRangeManager { 1153 private ArrayList<CdmaSmsBroadcastConfigInfo> mConfigList = 1154 new ArrayList<CdmaSmsBroadcastConfigInfo>(); 1155 1156 /** 1157 * Called when the list of enabled ranges has changed. This will be 1158 * followed by zero or more calls to {@link #addRange} followed by a 1159 * call to {@link #finishUpdate}. 1160 */ startUpdate()1161 protected void startUpdate() { 1162 mConfigList.clear(); 1163 } 1164 1165 /** 1166 * Called after {@link #startUpdate} to indicate a range of enabled 1167 * values. 1168 * @param startId the first id included in the range 1169 * @param endId the last id included in the range 1170 */ addRange(int startId, int endId, boolean selected)1171 protected void addRange(int startId, int endId, boolean selected) { 1172 mConfigList.add(new CdmaSmsBroadcastConfigInfo(startId, endId, 1173 1, selected)); 1174 } 1175 1176 /** 1177 * Called to indicate the end of a range update started by the previous 1178 * call to {@link #startUpdate}. 1179 * @return true if successful, false otherwise 1180 */ finishUpdate()1181 protected boolean finishUpdate() { 1182 if (mConfigList.isEmpty()) { 1183 return true; 1184 } else { 1185 CdmaSmsBroadcastConfigInfo[] configs = 1186 mConfigList.toArray(new CdmaSmsBroadcastConfigInfo[mConfigList.size()]); 1187 return setCdmaBroadcastConfig(configs); 1188 } 1189 } 1190 } 1191 1192 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setCellBroadcastConfig(SmsBroadcastConfigInfo[] configs)1193 private boolean setCellBroadcastConfig(SmsBroadcastConfigInfo[] configs) { 1194 if (DBG) { 1195 log("Calling setGsmBroadcastConfig with " + configs.length + " configurations"); 1196 } 1197 enforceNotOnHandlerThread("setCellBroadcastConfig"); 1198 Request setRequest = new Request(); 1199 synchronized (setRequest) { 1200 Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE, setRequest); 1201 1202 mPhone.mCi.setGsmBroadcastConfig(configs, response); 1203 1204 waitForResult(setRequest); 1205 } 1206 1207 return (boolean) setRequest.mResult; 1208 } 1209 setCellBroadcastActivation(boolean activate)1210 private boolean setCellBroadcastActivation(boolean activate) { 1211 if (DBG) { 1212 log("Calling setCellBroadcastActivation(" + activate + ')'); 1213 } 1214 1215 enforceNotOnHandlerThread("setCellBroadcastConfig"); 1216 Request setRequest = new Request(); 1217 synchronized (setRequest) { 1218 Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE, 1219 setRequest); 1220 1221 mPhone.mCi.setGsmBroadcastActivation(activate, response); 1222 waitForResult(setRequest); 1223 } 1224 1225 return (boolean) setRequest.mResult; 1226 } 1227 1228 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs)1229 private boolean setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs) { 1230 if (DBG) { 1231 log("Calling setCdmaBroadcastConfig with " + configs.length + " configurations"); 1232 } 1233 1234 enforceNotOnHandlerThread("setCdmaBroadcastConfig"); 1235 Request setRequest = new Request(); 1236 synchronized (setRequest) { 1237 Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE, setRequest); 1238 1239 mPhone.mCi.setCdmaBroadcastConfig(configs, response); 1240 1241 waitForResult(setRequest); 1242 } 1243 1244 return (boolean) setRequest.mResult; 1245 } 1246 setCdmaBroadcastActivation(boolean activate)1247 private boolean setCdmaBroadcastActivation(boolean activate) { 1248 if (DBG) { 1249 log("Calling setCdmaBroadcastActivation(" + activate + ")"); 1250 } 1251 1252 enforceNotOnHandlerThread("setCdmaBroadcastActivation"); 1253 Request setRequest = new Request(); 1254 synchronized (setRequest) { 1255 Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE, 1256 setRequest); 1257 1258 mPhone.mCi.setCdmaBroadcastActivation(activate, response); 1259 1260 waitForResult(setRequest); 1261 } 1262 1263 return (boolean) setRequest.mResult; 1264 } 1265 1266 @UnsupportedAppUsage log(String msg)1267 protected void log(String msg) { 1268 Rlog.d(LOG_TAG, msg); 1269 } 1270 loge(String msg)1271 protected void loge(String msg) { 1272 Rlog.e(LOG_TAG, msg); 1273 } 1274 loge(String msg, Throwable e)1275 protected void loge(String msg, Throwable e) { 1276 Rlog.e(LOG_TAG, msg, e); 1277 } 1278 1279 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isImsSmsSupported()1280 public boolean isImsSmsSupported() { 1281 return mDispatchersController.isIms(); 1282 } 1283 1284 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getImsSmsFormat()1285 public String getImsSmsFormat() { 1286 return mDispatchersController.getImsSmsFormat(); 1287 } 1288 1289 /** 1290 * @deprecated Use {@link #sendStoredText(String, String, Uri, String, PendingIntent, 1291 * PendingIntent)} instead 1292 */ 1293 @Deprecated 1294 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) sendStoredText(String callingPkg, Uri messageUri, String scAddress, PendingIntent sentIntent, PendingIntent deliveryIntent)1295 public void sendStoredText(String callingPkg, Uri messageUri, String scAddress, 1296 PendingIntent sentIntent, PendingIntent deliveryIntent) { 1297 sendStoredText(callingPkg, null, messageUri, scAddress, sentIntent, deliveryIntent); 1298 } 1299 sendStoredText(String callingPkg, String callingAttributionTag, Uri messageUri, String scAddress, PendingIntent sentIntent, PendingIntent deliveryIntent)1300 public void sendStoredText(String callingPkg, String callingAttributionTag, 1301 Uri messageUri, String scAddress, PendingIntent sentIntent, 1302 PendingIntent deliveryIntent) { 1303 if (!mSmsPermissions.checkCallingCanSendSms(callingPkg, callingAttributionTag, 1304 "Sending SMS message")) { 1305 returnUnspecifiedFailure(sentIntent); 1306 return; 1307 } 1308 if (Rlog.isLoggable("SMS", Log.VERBOSE)) { 1309 log("sendStoredText: scAddr=" + scAddress + " messageUri=" + messageUri 1310 + " sentIntent=" + sentIntent + " deliveryIntent=" + deliveryIntent); 1311 } 1312 final ContentResolver resolver = mContext.getContentResolver(); 1313 if (!isFailedOrDraft(resolver, messageUri)) { 1314 loge("sendStoredText: not FAILED or DRAFT message"); 1315 returnUnspecifiedFailure(sentIntent); 1316 return; 1317 } 1318 final String[] textAndAddress = loadTextAndAddress(resolver, messageUri); 1319 if (textAndAddress == null) { 1320 loge("sendStoredText: can not load text"); 1321 returnUnspecifiedFailure(sentIntent); 1322 return; 1323 } 1324 notifyIfOutgoingEmergencySms(textAndAddress[1]); 1325 textAndAddress[1] = filterDestAddress(textAndAddress[1]); 1326 mDispatchersController.sendText(textAndAddress[1], scAddress, textAndAddress[0], 1327 sentIntent, deliveryIntent, messageUri, callingPkg, 1328 true /* persistMessageForNonDefaultSmsApp */, SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, 1329 false /* expectMore */, SMS_MESSAGE_PERIOD_NOT_SPECIFIED, false /* isForVvm */, 1330 0L /* messageId */); 1331 } 1332 1333 /** 1334 * @deprecated Use {@link #sendStoredMultipartText(String, String, Uri, String, List, List)} 1335 * instead 1336 */ 1337 @Deprecated 1338 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) sendStoredMultipartText(String callingPkg, Uri messageUri, String scAddress, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents)1339 public void sendStoredMultipartText(String callingPkg, Uri messageUri, String scAddress, 1340 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) { 1341 sendStoredMultipartText(callingPkg, null, messageUri, scAddress, sentIntents, 1342 deliveryIntents); 1343 } 1344 sendStoredMultipartText(String callingPkg, String callingAttributionTag, Uri messageUri, String scAddress, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents)1345 public void sendStoredMultipartText(String callingPkg, 1346 String callingAttributionTag, Uri messageUri, String scAddress, 1347 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) { 1348 if (!mSmsPermissions.checkCallingCanSendSms(callingPkg, callingAttributionTag, 1349 "Sending SMS message")) { 1350 returnUnspecifiedFailure(sentIntents); 1351 return; 1352 } 1353 final ContentResolver resolver = mContext.getContentResolver(); 1354 if (!isFailedOrDraft(resolver, messageUri)) { 1355 loge("sendStoredMultipartText: not FAILED or DRAFT message"); 1356 returnUnspecifiedFailure(sentIntents); 1357 return; 1358 } 1359 final String[] textAndAddress = loadTextAndAddress(resolver, messageUri); 1360 if (textAndAddress == null) { 1361 loge("sendStoredMultipartText: can not load text"); 1362 returnUnspecifiedFailure(sentIntents); 1363 return; 1364 } 1365 final ArrayList<String> parts = SmsManager.getDefault().divideMessage(textAndAddress[0]); 1366 if (parts == null || parts.size() < 1) { 1367 loge("sendStoredMultipartText: can not divide text"); 1368 returnUnspecifiedFailure(sentIntents); 1369 return; 1370 } 1371 notifyIfOutgoingEmergencySms(textAndAddress[1]); 1372 textAndAddress[1] = filterDestAddress(textAndAddress[1]); 1373 1374 if (parts.size() > 1 && parts.size() < 10 && !SmsMessage.hasEmsSupport()) { 1375 for (int i = 0; i < parts.size(); i++) { 1376 // If EMS is not supported, we have to break down EMS into single segment SMS 1377 // and add page info " x/y". 1378 String singlePart = parts.get(i); 1379 if (SmsMessage.shouldAppendPageNumberAsPrefix()) { 1380 singlePart = String.valueOf(i + 1) + '/' + parts.size() + ' ' + singlePart; 1381 } else { 1382 singlePart = singlePart.concat(' ' + String.valueOf(i + 1) + '/' 1383 + parts.size()); 1384 } 1385 1386 PendingIntent singleSentIntent = null; 1387 if (sentIntents != null && sentIntents.size() > i) { 1388 singleSentIntent = sentIntents.get(i); 1389 } 1390 1391 PendingIntent singleDeliveryIntent = null; 1392 if (deliveryIntents != null && deliveryIntents.size() > i) { 1393 singleDeliveryIntent = deliveryIntents.get(i); 1394 } 1395 1396 mDispatchersController.sendText(textAndAddress[1], scAddress, singlePart, 1397 singleSentIntent, singleDeliveryIntent, messageUri, callingPkg, 1398 true /* persistMessageForNonDefaultSmsApp */, 1399 SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, 1400 false /* expectMore */, SMS_MESSAGE_PERIOD_NOT_SPECIFIED, 1401 false /* isForVvm */, 0L /* messageId */); 1402 } 1403 return; 1404 } 1405 1406 mDispatchersController.sendMultipartText( 1407 textAndAddress[1], // destAddress 1408 scAddress, 1409 parts, 1410 (ArrayList<PendingIntent>) sentIntents, 1411 (ArrayList<PendingIntent>) deliveryIntents, 1412 messageUri, 1413 callingPkg, 1414 true /* persistMessageForNonDefaultSmsApp */, 1415 SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, 1416 false /* expectMore */, 1417 SMS_MESSAGE_PERIOD_NOT_SPECIFIED, 1418 0L /* messageId */); 1419 } 1420 getSmsCapacityOnIcc(String callingPackage, String callingFeatureId)1421 public int getSmsCapacityOnIcc(String callingPackage, String callingFeatureId) { 1422 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 1423 mContext, mPhone.getSubId(), callingPackage, callingFeatureId, 1424 "getSmsCapacityOnIcc")) { 1425 return 0; 1426 } 1427 1428 int numberOnIcc = 0; 1429 if (mPhone.getIccRecordsLoaded()) { 1430 final UiccProfile uiccProfile = UiccController.getInstance() 1431 .getUiccProfileForPhone(mPhone.getPhoneId()); 1432 if(uiccProfile != null) { 1433 numberOnIcc = uiccProfile.getIccRecords().getSmsCapacityOnIcc(); 1434 } else { 1435 loge("uiccProfile is null"); 1436 } 1437 } else { 1438 loge("getSmsCapacityOnIcc - aborting, no icc card present."); 1439 } 1440 1441 log("getSmsCapacityOnIcc().numberOnIcc = " + numberOnIcc); 1442 return numberOnIcc; 1443 } 1444 isFailedOrDraft(ContentResolver resolver, Uri messageUri)1445 private boolean isFailedOrDraft(ContentResolver resolver, Uri messageUri) { 1446 // Clear the calling identity and query the database using the phone user id 1447 // Otherwise the AppOps check in TelephonyProvider would complain about mismatch 1448 // between the calling uid and the package uid 1449 final long identity = Binder.clearCallingIdentity(); 1450 Cursor cursor = null; 1451 try { 1452 cursor = resolver.query( 1453 messageUri, 1454 new String[]{ Telephony.Sms.TYPE }, 1455 null/*selection*/, 1456 null/*selectionArgs*/, 1457 null/*sortOrder*/); 1458 if (cursor != null && cursor.moveToFirst()) { 1459 final int type = cursor.getInt(0); 1460 return type == Telephony.Sms.MESSAGE_TYPE_DRAFT 1461 || type == Telephony.Sms.MESSAGE_TYPE_FAILED; 1462 } 1463 } catch (SQLiteException e) { 1464 loge("isFailedOrDraft: query message type failed", e); 1465 } finally { 1466 if (cursor != null) { 1467 cursor.close(); 1468 } 1469 Binder.restoreCallingIdentity(identity); 1470 } 1471 return false; 1472 } 1473 1474 // Return an array including both the SMS text (0) and address (1) loadTextAndAddress(ContentResolver resolver, Uri messageUri)1475 private String[] loadTextAndAddress(ContentResolver resolver, Uri messageUri) { 1476 // Clear the calling identity and query the database using the phone user id 1477 // Otherwise the AppOps check in TelephonyProvider would complain about mismatch 1478 // between the calling uid and the package uid 1479 final long identity = Binder.clearCallingIdentity(); 1480 Cursor cursor = null; 1481 try { 1482 cursor = resolver.query( 1483 messageUri, 1484 new String[]{ 1485 Telephony.Sms.BODY, 1486 Telephony.Sms.ADDRESS 1487 }, 1488 null/*selection*/, 1489 null/*selectionArgs*/, 1490 null/*sortOrder*/); 1491 if (cursor != null && cursor.moveToFirst()) { 1492 return new String[]{ cursor.getString(0), cursor.getString(1) }; 1493 } 1494 } catch (SQLiteException e) { 1495 loge("loadText: query message text failed", e); 1496 } finally { 1497 if (cursor != null) { 1498 cursor.close(); 1499 } 1500 Binder.restoreCallingIdentity(identity); 1501 } 1502 return null; 1503 } 1504 1505 @VisibleForTesting notifyIfOutgoingEmergencySms(String destAddr)1506 public void notifyIfOutgoingEmergencySms(String destAddr) { 1507 Phone[] allPhones = mPhoneFactoryProxy.getPhones(); 1508 EmergencyNumber emergencyNumber = mPhone.getEmergencyNumberTracker().getEmergencyNumber( 1509 destAddr); 1510 if (emergencyNumber != null) { 1511 mPhone.notifyOutgoingEmergencySms(emergencyNumber); 1512 } else if (allPhones.length > 1) { 1513 // If there are multiple active SIMs, check all instances: 1514 for (Phone phone : allPhones) { 1515 // If the current iteration was already checked, skip: 1516 if (phone.getPhoneId() == mPhone.getPhoneId()) { 1517 continue; 1518 } 1519 emergencyNumber = phone.getEmergencyNumberTracker() 1520 .getEmergencyNumber(destAddr); 1521 if (emergencyNumber != null) { 1522 mPhone.notifyOutgoingEmergencySms(emergencyNumber); 1523 break; 1524 } 1525 } 1526 } 1527 } 1528 returnUnspecifiedFailure(PendingIntent pi)1529 private void returnUnspecifiedFailure(PendingIntent pi) { 1530 if (pi != null) { 1531 try { 1532 pi.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE); 1533 } catch (PendingIntent.CanceledException e) { 1534 // ignore 1535 } 1536 } 1537 } 1538 returnUnspecifiedFailure(List<PendingIntent> pis)1539 private void returnUnspecifiedFailure(List<PendingIntent> pis) { 1540 if (pis == null) { 1541 return; 1542 } 1543 for (PendingIntent pi : pis) { 1544 returnUnspecifiedFailure(pi); 1545 } 1546 } 1547 1548 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) filterDestAddress(String destAddr)1549 private String filterDestAddress(String destAddr) { 1550 String result = SmsNumberUtils.filterDestAddr(mContext, mPhone.getSubId(), destAddr); 1551 return result != null ? result : destAddr; 1552 } 1553 waitForResult(Request request)1554 private void waitForResult(Request request) { 1555 synchronized (request) { 1556 while (!request.mStatus.get()) { 1557 try { 1558 request.wait(); 1559 } catch (InterruptedException e) { 1560 log("Interrupted while waiting for result"); 1561 } 1562 } 1563 } 1564 } 1565 1566 /** 1567 * Get InboundSmsHandler for the phone. 1568 */ getInboundSmsHandler(boolean is3gpp2)1569 public InboundSmsHandler getInboundSmsHandler(boolean is3gpp2) { 1570 return mDispatchersController.getInboundSmsHandler(is3gpp2); 1571 } 1572 dump(FileDescriptor fd, PrintWriter pw, String[] args)1573 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1574 pw.println("Enabled GSM channels: " + mCellBroadcastRangeManager); 1575 pw.println("Enabled CDMA channels: " + mCdmaBroadcastRangeManager); 1576 pw.println("CellBroadcast log:"); 1577 mCellBroadcastLocalLog.dump(fd, pw, args); 1578 pw.println("SMS dispatcher controller log:"); 1579 mDispatchersController.dump(fd, pw, args); 1580 pw.flush(); 1581 } 1582 } 1583