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