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