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.app.AppOpsManager; 25 import android.app.PendingIntent; 26 import android.content.ContentResolver; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.pm.PackageManager; 30 import android.database.Cursor; 31 import android.database.sqlite.SQLiteException; 32 import android.net.Uri; 33 import android.os.AsyncResult; 34 import android.os.Binder; 35 import android.os.Handler; 36 import android.os.Message; 37 import android.os.UserManager; 38 import android.provider.Telephony; 39 import android.service.carrier.CarrierMessagingService; 40 import android.telephony.Rlog; 41 import android.telephony.SmsManager; 42 import android.telephony.SmsMessage; 43 import android.telephony.TelephonyManager; 44 import android.util.Log; 45 46 import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo; 47 import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; 48 import com.android.internal.telephony.uicc.IccConstants; 49 import com.android.internal.telephony.uicc.IccFileHandler; 50 import com.android.internal.telephony.uicc.IccUtils; 51 import com.android.internal.telephony.uicc.UiccController; 52 import com.android.internal.util.HexDump; 53 54 import java.util.ArrayList; 55 import java.util.Arrays; 56 import java.util.List; 57 58 /** 59 * IccSmsInterfaceManager to provide an inter-process communication to 60 * access Sms in Icc. 61 */ 62 public class IccSmsInterfaceManager { 63 static final String LOG_TAG = "IccSmsInterfaceManager"; 64 static final boolean DBG = true; 65 66 protected final Object mLock = new Object(); 67 protected boolean mSuccess; 68 private List<SmsRawData> mSms; 69 70 private CellBroadcastRangeManager mCellBroadcastRangeManager = 71 new CellBroadcastRangeManager(); 72 private CdmaBroadcastRangeManager mCdmaBroadcastRangeManager = 73 new CdmaBroadcastRangeManager(); 74 75 private static final int EVENT_LOAD_DONE = 1; 76 private static final int EVENT_UPDATE_DONE = 2; 77 protected static final int EVENT_SET_BROADCAST_ACTIVATION_DONE = 3; 78 protected static final int EVENT_SET_BROADCAST_CONFIG_DONE = 4; 79 private static final int SMS_CB_CODE_SCHEME_MIN = 0; 80 private static final int SMS_CB_CODE_SCHEME_MAX = 255; 81 82 protected Phone mPhone; 83 final protected Context mContext; 84 final protected AppOpsManager mAppOps; 85 final private UserManager mUserManager; 86 protected SMSDispatcher mDispatcher; 87 88 protected Handler mHandler = new Handler() { 89 @Override 90 public void handleMessage(Message msg) { 91 AsyncResult ar; 92 93 switch (msg.what) { 94 case EVENT_UPDATE_DONE: 95 ar = (AsyncResult) msg.obj; 96 synchronized (mLock) { 97 mSuccess = (ar.exception == null); 98 mLock.notifyAll(); 99 } 100 break; 101 case EVENT_LOAD_DONE: 102 ar = (AsyncResult)msg.obj; 103 synchronized (mLock) { 104 if (ar.exception == null) { 105 mSms = buildValidRawData((ArrayList<byte[]>) ar.result); 106 //Mark SMS as read after importing it from card. 107 markMessagesAsRead((ArrayList<byte[]>) ar.result); 108 } else { 109 if (Rlog.isLoggable("SMS", Log.DEBUG)) { 110 log("Cannot load Sms records"); 111 } 112 mSms = null; 113 } 114 mLock.notifyAll(); 115 } 116 break; 117 case EVENT_SET_BROADCAST_ACTIVATION_DONE: 118 case EVENT_SET_BROADCAST_CONFIG_DONE: 119 ar = (AsyncResult) msg.obj; 120 synchronized (mLock) { 121 mSuccess = (ar.exception == null); 122 mLock.notifyAll(); 123 } 124 break; 125 } 126 } 127 }; 128 IccSmsInterfaceManager(Phone phone)129 protected IccSmsInterfaceManager(Phone phone) { 130 mPhone = phone; 131 mContext = phone.getContext(); 132 mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 133 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 134 mDispatcher = new ImsSMSDispatcher(phone, 135 phone.mSmsStorageMonitor, phone.mSmsUsageMonitor); 136 } 137 markMessagesAsRead(ArrayList<byte[]> messages)138 protected void markMessagesAsRead(ArrayList<byte[]> messages) { 139 if (messages == null) { 140 return; 141 } 142 143 //IccFileHandler can be null, if icc card is absent. 144 IccFileHandler fh = mPhone.getIccFileHandler(); 145 if (fh == null) { 146 //shouldn't really happen, as messages are marked as read, only 147 //after importing it from icc. 148 if (Rlog.isLoggable("SMS", Log.DEBUG)) { 149 log("markMessagesAsRead - aborting, no icc card present."); 150 } 151 return; 152 } 153 154 int count = messages.size(); 155 156 for (int i = 0; i < count; i++) { 157 byte[] ba = messages.get(i); 158 if (ba[0] == STATUS_ON_ICC_UNREAD) { 159 int n = ba.length; 160 byte[] nba = new byte[n - 1]; 161 System.arraycopy(ba, 1, nba, 0, n - 1); 162 byte[] record = makeSmsRecordData(STATUS_ON_ICC_READ, nba); 163 fh.updateEFLinearFixed(IccConstants.EF_SMS, i + 1, record, null, null); 164 if (Rlog.isLoggable("SMS", Log.DEBUG)) { 165 log("SMS " + (i + 1) + " marked as read"); 166 } 167 } 168 } 169 } 170 updatePhoneObject(Phone phone)171 protected void updatePhoneObject(Phone phone) { 172 mPhone = phone; 173 mDispatcher.updatePhoneObject(phone); 174 } 175 enforceReceiveAndSend(String message)176 protected void enforceReceiveAndSend(String message) { 177 mContext.enforceCallingOrSelfPermission( 178 Manifest.permission.RECEIVE_SMS, message); 179 mContext.enforceCallingOrSelfPermission( 180 Manifest.permission.SEND_SMS, message); 181 } 182 183 /** 184 * Update the specified message on the Icc. 185 * 186 * @param index record index of message to update 187 * @param status new message status (STATUS_ON_ICC_READ, 188 * STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT, 189 * STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE) 190 * @param pdu the raw PDU to store 191 * @return success or not 192 * 193 */ 194 195 public boolean updateMessageOnIccEf(String callingPackage, int index, int status, byte[] pdu)196 updateMessageOnIccEf(String callingPackage, int index, int status, byte[] pdu) { 197 if (DBG) log("updateMessageOnIccEf: index=" + index + 198 " status=" + status + " ==> " + 199 "("+ Arrays.toString(pdu) + ")"); 200 enforceReceiveAndSend("Updating message on Icc"); 201 if (mAppOps.noteOp(AppOpsManager.OP_WRITE_ICC_SMS, Binder.getCallingUid(), 202 callingPackage) != AppOpsManager.MODE_ALLOWED) { 203 return false; 204 } 205 synchronized(mLock) { 206 mSuccess = false; 207 Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE); 208 209 if (status == STATUS_ON_ICC_FREE) { 210 // RIL_REQUEST_DELETE_SMS_ON_SIM vs RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM 211 // Special case FREE: call deleteSmsOnSim/Ruim instead of 212 // manipulating the record 213 // Will eventually fail if icc card is not present. 214 if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) { 215 mPhone.mCi.deleteSmsOnSim(index, response); 216 } else { 217 mPhone.mCi.deleteSmsOnRuim(index, response); 218 } 219 } else { 220 //IccFilehandler can be null if ICC card is not present. 221 IccFileHandler fh = mPhone.getIccFileHandler(); 222 if (fh == null) { 223 response.recycle(); 224 return mSuccess; /* is false */ 225 } 226 byte[] record = makeSmsRecordData(status, pdu); 227 fh.updateEFLinearFixed( 228 IccConstants.EF_SMS, 229 index, record, null, response); 230 } 231 try { 232 mLock.wait(); 233 } catch (InterruptedException e) { 234 log("interrupted while trying to update by index"); 235 } 236 } 237 return mSuccess; 238 } 239 240 /** 241 * Copy a raw SMS PDU to the Icc. 242 * 243 * @param pdu the raw PDU to store 244 * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD, 245 * STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT) 246 * @return success or not 247 * 248 */ copyMessageToIccEf(String callingPackage, int status, byte[] pdu, byte[] smsc)249 public boolean copyMessageToIccEf(String callingPackage, int status, byte[] pdu, byte[] smsc) { 250 //NOTE smsc not used in RUIM 251 if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " + 252 "pdu=("+ Arrays.toString(pdu) + 253 "), smsc=(" + Arrays.toString(smsc) +")"); 254 enforceReceiveAndSend("Copying message to Icc"); 255 if (mAppOps.noteOp(AppOpsManager.OP_WRITE_ICC_SMS, Binder.getCallingUid(), 256 callingPackage) != AppOpsManager.MODE_ALLOWED) { 257 return false; 258 } 259 synchronized(mLock) { 260 mSuccess = false; 261 Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE); 262 263 //RIL_REQUEST_WRITE_SMS_TO_SIM vs RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM 264 if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) { 265 mPhone.mCi.writeSmsToSim(status, IccUtils.bytesToHexString(smsc), 266 IccUtils.bytesToHexString(pdu), response); 267 } else { 268 mPhone.mCi.writeSmsToRuim(status, IccUtils.bytesToHexString(pdu), 269 response); 270 } 271 272 try { 273 mLock.wait(); 274 } catch (InterruptedException e) { 275 log("interrupted while trying to update by index"); 276 } 277 } 278 return mSuccess; 279 } 280 281 /** 282 * Retrieves all messages currently stored on Icc. 283 * 284 * @return list of SmsRawData of all sms on Icc 285 */ 286 getAllMessagesFromIccEf(String callingPackage)287 public List<SmsRawData> getAllMessagesFromIccEf(String callingPackage) { 288 if (DBG) log("getAllMessagesFromEF"); 289 290 mContext.enforceCallingOrSelfPermission( 291 Manifest.permission.RECEIVE_SMS, 292 "Reading messages from Icc"); 293 if (mAppOps.noteOp(AppOpsManager.OP_READ_ICC_SMS, Binder.getCallingUid(), 294 callingPackage) != AppOpsManager.MODE_ALLOWED) { 295 return new ArrayList<SmsRawData>(); 296 } 297 synchronized(mLock) { 298 299 IccFileHandler fh = mPhone.getIccFileHandler(); 300 if (fh == null) { 301 Rlog.e(LOG_TAG, "Cannot load Sms records. No icc card?"); 302 mSms = null; 303 return mSms; 304 } 305 306 Message response = mHandler.obtainMessage(EVENT_LOAD_DONE); 307 fh.loadEFLinearFixedAll(IccConstants.EF_SMS, response); 308 309 try { 310 mLock.wait(); 311 } catch (InterruptedException e) { 312 log("interrupted while trying to load from the Icc"); 313 } 314 } 315 return mSms; 316 } 317 318 /** 319 * A permissions check before passing to {@link IccSmsInterfaceManager#sendDataInternal}. 320 * This method checks if the calling package or itself has the permission to send the data sms. 321 */ sendDataWithSelfPermissions(String callingPackage, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)322 public void sendDataWithSelfPermissions(String callingPackage, String destAddr, String scAddr, 323 int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 324 mPhone.getContext().enforceCallingOrSelfPermission( 325 Manifest.permission.SEND_SMS, 326 "Sending SMS message"); 327 sendDataInternal(callingPackage, destAddr, scAddr, destPort, data, sentIntent, 328 deliveryIntent); 329 } 330 331 /** 332 * A permissions check before passing to {@link IccSmsInterfaceManager#sendDataInternal}. 333 * This method checks only if the calling package has the permission to send the data sms. 334 */ sendData(String callingPackage, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)335 public void sendData(String callingPackage, String destAddr, String scAddr, int destPort, 336 byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 337 mPhone.getContext().enforceCallingPermission( 338 Manifest.permission.SEND_SMS, 339 "Sending SMS message"); 340 sendDataInternal(callingPackage, destAddr, scAddr, destPort, data, sentIntent, 341 deliveryIntent); 342 } 343 344 /** 345 * Send a data based SMS to a specific application port. 346 * 347 * @param destAddr the address to send the message to 348 * @param scAddr is the service center address or null to use 349 * the current default SMSC 350 * @param destPort the port to deliver the message to 351 * @param data the body of the message to send 352 * @param sentIntent if not NULL this <code>PendingIntent</code> is 353 * broadcast when the message is successfully sent, or failed. 354 * The result code will be <code>Activity.RESULT_OK<code> for success, 355 * or one of these errors:<br> 356 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 357 * <code>RESULT_ERROR_RADIO_OFF</code><br> 358 * <code>RESULT_ERROR_NULL_PDU</code><br> 359 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 360 * the extra "errorCode" containing a radio technology specific value, 361 * generally only useful for troubleshooting.<br> 362 * The per-application based SMS control checks sentIntent. If sentIntent 363 * is NULL the caller will be checked against all unknown applications, 364 * which cause smaller number of SMS to be sent in checking period. 365 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 366 * broadcast when the message is delivered to the recipient. The 367 * raw pdu of the status report is in the extended data ("pdu"). 368 */ 369 sendDataInternal(String callingPackage, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)370 private void sendDataInternal(String callingPackage, String destAddr, String scAddr, 371 int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 372 if (Rlog.isLoggable("SMS", Log.VERBOSE)) { 373 log("sendData: destAddr=" + destAddr + " scAddr=" + scAddr + " destPort=" + 374 destPort + " data='"+ HexDump.toHexString(data) + "' sentIntent=" + 375 sentIntent + " deliveryIntent=" + deliveryIntent); 376 } 377 if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), 378 callingPackage) != AppOpsManager.MODE_ALLOWED) { 379 return; 380 } 381 destAddr = filterDestAddress(destAddr); 382 mDispatcher.sendData(destAddr, scAddr, destPort, data, sentIntent, deliveryIntent); 383 } 384 385 /** 386 * A permissions check before passing to {@link IccSmsInterfaceManager#sendTextInternal}. 387 * This method checks only if the calling package has the permission to send the sms. 388 */ sendText(String callingPackage, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp)389 public void sendText(String callingPackage, String destAddr, String scAddr, 390 String text, PendingIntent sentIntent, PendingIntent deliveryIntent, 391 boolean persistMessageForNonDefaultSmsApp) { 392 mPhone.getContext().enforceCallingPermission( 393 Manifest.permission.SEND_SMS, 394 "Sending SMS message"); 395 sendTextInternal(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent, 396 persistMessageForNonDefaultSmsApp); 397 } 398 399 /** 400 * A permissions check before passing to {@link IccSmsInterfaceManager#sendTextInternal}. 401 * This method checks if the calling package or itself has the permission to send the sms. 402 */ sendTextWithSelfPermissions(String callingPackage, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage)403 public void sendTextWithSelfPermissions(String callingPackage, String destAddr, String scAddr, 404 String text, PendingIntent sentIntent, PendingIntent deliveryIntent, 405 boolean persistMessage) { 406 mPhone.getContext().enforceCallingOrSelfPermission( 407 Manifest.permission.SEND_SMS, 408 "Sending SMS message"); 409 sendTextInternal(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent, 410 persistMessage); 411 } 412 413 /** 414 * Send a text based SMS. 415 * 416 * @param destAddr the address to send the message to 417 * @param scAddr is the service center address or null to use 418 * the current default SMSC 419 * @param text the body of the message to send 420 * @param sentIntent if not NULL this <code>PendingIntent</code> is 421 * broadcast when the message is successfully sent, or failed. 422 * The result code will be <code>Activity.RESULT_OK<code> for success, 423 * or one of these errors:<br> 424 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 425 * <code>RESULT_ERROR_RADIO_OFF</code><br> 426 * <code>RESULT_ERROR_NULL_PDU</code><br> 427 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 428 * the extra "errorCode" containing a radio technology specific value, 429 * generally only useful for troubleshooting.<br> 430 * The per-application based SMS control checks sentIntent. If sentIntent 431 * is NULL the caller will be checked against all unknown applications, 432 * which cause smaller number of SMS to be sent in checking period. 433 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 434 * broadcast when the message is delivered to the recipient. The 435 * raw pdu of the status report is in the extended data ("pdu"). 436 */ 437 sendTextInternal(String callingPackage, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp)438 private void sendTextInternal(String callingPackage, String destAddr, String scAddr, 439 String text, PendingIntent sentIntent, PendingIntent deliveryIntent, 440 boolean persistMessageForNonDefaultSmsApp) { 441 if (Rlog.isLoggable("SMS", Log.VERBOSE)) { 442 log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr + 443 " text='"+ text + "' sentIntent=" + 444 sentIntent + " deliveryIntent=" + deliveryIntent); 445 } 446 if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), 447 callingPackage) != AppOpsManager.MODE_ALLOWED) { 448 return; 449 } 450 if (!persistMessageForNonDefaultSmsApp) { 451 enforcePrivilegedAppPermissions(); 452 } 453 destAddr = filterDestAddress(destAddr); 454 mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent, 455 null/*messageUri*/, callingPackage, persistMessageForNonDefaultSmsApp); 456 } 457 458 /** 459 * Inject an SMS PDU into the android application framework. 460 * 461 * @param pdu is the byte array of pdu to be injected into android application framework 462 * @param format is the format of SMS pdu (3gpp or 3gpp2) 463 * @param receivedIntent if not NULL this <code>PendingIntent</code> is 464 * broadcast when the message is successfully received by the 465 * android application framework. This intent is broadcasted at 466 * the same time an SMS received from radio is acknowledged back. 467 */ injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent)468 public void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) { 469 enforcePrivilegedAppPermissions(); 470 if (Rlog.isLoggable("SMS", Log.VERBOSE)) { 471 log("pdu: " + pdu + 472 "\n format=" + format + 473 "\n receivedIntent=" + receivedIntent); 474 } 475 mDispatcher.injectSmsPdu(pdu, format, receivedIntent); 476 } 477 478 /** 479 * Send a multi-part text based SMS. 480 * 481 * @param destAddr the address to send the message to 482 * @param scAddr is the service center address or null to use 483 * the current default SMSC 484 * @param parts an <code>ArrayList</code> of strings that, in order, 485 * comprise the original message 486 * @param sentIntents if not null, an <code>ArrayList</code> of 487 * <code>PendingIntent</code>s (one for each message part) that is 488 * broadcast when the corresponding message part has been sent. 489 * The result code will be <code>Activity.RESULT_OK<code> for success, 490 * or one of these errors: 491 * <code>RESULT_ERROR_GENERIC_FAILURE</code> 492 * <code>RESULT_ERROR_RADIO_OFF</code> 493 * <code>RESULT_ERROR_NULL_PDU</code>. 494 * The per-application based SMS control checks sentIntent. If sentIntent 495 * is NULL the caller will be checked against all unknown applications, 496 * which cause smaller number of SMS to be sent in checking period. 497 * @param deliveryIntents if not null, an <code>ArrayList</code> of 498 * <code>PendingIntent</code>s (one for each message part) that is 499 * broadcast when the corresponding message part has been delivered 500 * to the recipient. The raw pdu of the status report is in the 501 * extended data ("pdu"). 502 */ 503 sendMultipartText(String callingPackage, String destAddr, String scAddr, List<String> parts, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp)504 public void sendMultipartText(String callingPackage, String destAddr, String scAddr, 505 List<String> parts, List<PendingIntent> sentIntents, 506 List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp) { 507 mPhone.getContext().enforceCallingPermission( 508 Manifest.permission.SEND_SMS, 509 "Sending SMS message"); 510 if (!persistMessageForNonDefaultSmsApp) { 511 // Only allow carrier app or carrier ims to skip auto message persistence. 512 enforcePrivilegedAppPermissions(); 513 } 514 if (Rlog.isLoggable("SMS", Log.VERBOSE)) { 515 int i = 0; 516 for (String part : parts) { 517 log("sendMultipartText: destAddr=" + destAddr + ", srAddr=" + scAddr + 518 ", part[" + (i++) + "]=" + part); 519 } 520 } 521 if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), 522 callingPackage) != AppOpsManager.MODE_ALLOWED) { 523 return; 524 } 525 526 destAddr = filterDestAddress(destAddr); 527 528 if (parts.size() > 1 && parts.size() < 10 && !SmsMessage.hasEmsSupport()) { 529 for (int i = 0; i < parts.size(); i++) { 530 // If EMS is not supported, we have to break down EMS into single segment SMS 531 // and add page info " x/y". 532 String singlePart = parts.get(i); 533 if (SmsMessage.shouldAppendPageNumberAsPrefix()) { 534 singlePart = String.valueOf(i + 1) + '/' + parts.size() + ' ' + singlePart; 535 } else { 536 singlePart = singlePart.concat(' ' + String.valueOf(i + 1) + '/' + parts.size()); 537 } 538 539 PendingIntent singleSentIntent = null; 540 if (sentIntents != null && sentIntents.size() > i) { 541 singleSentIntent = sentIntents.get(i); 542 } 543 544 PendingIntent singleDeliveryIntent = null; 545 if (deliveryIntents != null && deliveryIntents.size() > i) { 546 singleDeliveryIntent = deliveryIntents.get(i); 547 } 548 549 mDispatcher.sendText(destAddr, scAddr, singlePart, 550 singleSentIntent, singleDeliveryIntent, 551 null/*messageUri*/, callingPackage, 552 persistMessageForNonDefaultSmsApp); 553 } 554 return; 555 } 556 557 mDispatcher.sendMultipartText(destAddr, scAddr, (ArrayList<String>) parts, 558 (ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents, 559 null/*messageUri*/, callingPackage, persistMessageForNonDefaultSmsApp); 560 } 561 562 getPremiumSmsPermission(String packageName)563 public int getPremiumSmsPermission(String packageName) { 564 return mDispatcher.getPremiumSmsPermission(packageName); 565 } 566 567 setPremiumSmsPermission(String packageName, int permission)568 public void setPremiumSmsPermission(String packageName, int permission) { 569 mDispatcher.setPremiumSmsPermission(packageName, permission); 570 } 571 572 /** 573 * create SmsRawData lists from all sms record byte[] 574 * Use null to indicate "free" record 575 * 576 * @param messages List of message records from EF_SMS. 577 * @return SmsRawData list of all in-used records 578 */ buildValidRawData(ArrayList<byte[]> messages)579 protected ArrayList<SmsRawData> buildValidRawData(ArrayList<byte[]> messages) { 580 int count = messages.size(); 581 ArrayList<SmsRawData> ret; 582 583 ret = new ArrayList<SmsRawData>(count); 584 585 for (int i = 0; i < count; i++) { 586 byte[] ba = messages.get(i); 587 if (ba[0] == STATUS_ON_ICC_FREE) { 588 ret.add(null); 589 } else { 590 ret.add(new SmsRawData(messages.get(i))); 591 } 592 } 593 594 return ret; 595 } 596 597 /** 598 * Generates an EF_SMS record from status and raw PDU. 599 * 600 * @param status Message status. See TS 51.011 10.5.3. 601 * @param pdu Raw message PDU. 602 * @return byte array for the record. 603 */ makeSmsRecordData(int status, byte[] pdu)604 protected byte[] makeSmsRecordData(int status, byte[] pdu) { 605 byte[] data; 606 if (PhoneConstants.PHONE_TYPE_GSM == mPhone.getPhoneType()) { 607 data = new byte[SmsManager.SMS_RECORD_LENGTH]; 608 } else { 609 data = new byte[SmsManager.CDMA_SMS_RECORD_LENGTH]; 610 } 611 612 // Status bits for this record. See TS 51.011 10.5.3 613 data[0] = (byte)(status & 7); 614 615 System.arraycopy(pdu, 0, data, 1, pdu.length); 616 617 // Pad out with 0xFF's. 618 for (int j = pdu.length+1; j < data.length; j++) { 619 data[j] = -1; 620 } 621 622 return data; 623 } 624 enableCellBroadcast(int messageIdentifier, int ranType)625 public boolean enableCellBroadcast(int messageIdentifier, int ranType) { 626 return enableCellBroadcastRange(messageIdentifier, messageIdentifier, ranType); 627 } 628 disableCellBroadcast(int messageIdentifier, int ranType)629 public boolean disableCellBroadcast(int messageIdentifier, int ranType) { 630 return disableCellBroadcastRange(messageIdentifier, messageIdentifier, ranType); 631 } 632 enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType)633 public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) { 634 if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_GSM) { 635 return enableGsmBroadcastRange(startMessageId, endMessageId); 636 } else if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA) { 637 return enableCdmaBroadcastRange(startMessageId, endMessageId); 638 } else { 639 throw new IllegalArgumentException("Not a supportted RAN Type"); 640 } 641 } 642 disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType)643 public boolean disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) { 644 if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_GSM ) { 645 return disableGsmBroadcastRange(startMessageId, endMessageId); 646 } else if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA) { 647 return disableCdmaBroadcastRange(startMessageId, endMessageId); 648 } else { 649 throw new IllegalArgumentException("Not a supportted RAN Type"); 650 } 651 } 652 enableGsmBroadcastRange(int startMessageId, int endMessageId)653 synchronized public boolean enableGsmBroadcastRange(int startMessageId, int endMessageId) { 654 655 Context context = mPhone.getContext(); 656 657 context.enforceCallingPermission( 658 "android.permission.RECEIVE_SMS", 659 "Enabling cell broadcast SMS"); 660 661 String client = context.getPackageManager().getNameForUid( 662 Binder.getCallingUid()); 663 664 if (!mCellBroadcastRangeManager.enableRange(startMessageId, endMessageId, client)) { 665 log("Failed to add GSM cell broadcast subscription for MID range " + startMessageId 666 + " to " + endMessageId + " from client " + client); 667 return false; 668 } 669 670 if (DBG) 671 log("Added GSM cell broadcast subscription for MID range " + startMessageId 672 + " to " + endMessageId + " from client " + client); 673 674 setCellBroadcastActivation(!mCellBroadcastRangeManager.isEmpty()); 675 676 return true; 677 } 678 disableGsmBroadcastRange(int startMessageId, int endMessageId)679 synchronized public boolean disableGsmBroadcastRange(int startMessageId, int endMessageId) { 680 681 Context context = mPhone.getContext(); 682 683 context.enforceCallingPermission( 684 "android.permission.RECEIVE_SMS", 685 "Disabling cell broadcast SMS"); 686 687 String client = context.getPackageManager().getNameForUid( 688 Binder.getCallingUid()); 689 690 if (!mCellBroadcastRangeManager.disableRange(startMessageId, endMessageId, client)) { 691 log("Failed to remove GSM cell broadcast subscription for MID range " + startMessageId 692 + " to " + endMessageId + " from client " + client); 693 return false; 694 } 695 696 if (DBG) 697 log("Removed GSM cell broadcast subscription for MID range " + startMessageId 698 + " to " + endMessageId + " from client " + client); 699 700 setCellBroadcastActivation(!mCellBroadcastRangeManager.isEmpty()); 701 702 return true; 703 } 704 enableCdmaBroadcastRange(int startMessageId, int endMessageId)705 synchronized public boolean enableCdmaBroadcastRange(int startMessageId, int endMessageId) { 706 707 Context context = mPhone.getContext(); 708 709 context.enforceCallingPermission( 710 "android.permission.RECEIVE_SMS", 711 "Enabling cdma broadcast SMS"); 712 713 String client = context.getPackageManager().getNameForUid( 714 Binder.getCallingUid()); 715 716 if (!mCdmaBroadcastRangeManager.enableRange(startMessageId, endMessageId, client)) { 717 log("Failed to add cdma broadcast subscription for MID range " + startMessageId 718 + " to " + endMessageId + " from client " + client); 719 return false; 720 } 721 722 if (DBG) 723 log("Added cdma broadcast subscription for MID range " + startMessageId 724 + " to " + endMessageId + " from client " + client); 725 726 setCdmaBroadcastActivation(!mCdmaBroadcastRangeManager.isEmpty()); 727 728 return true; 729 } 730 disableCdmaBroadcastRange(int startMessageId, int endMessageId)731 synchronized public boolean disableCdmaBroadcastRange(int startMessageId, int endMessageId) { 732 733 Context context = mPhone.getContext(); 734 735 context.enforceCallingPermission( 736 "android.permission.RECEIVE_SMS", 737 "Disabling cell broadcast SMS"); 738 739 String client = context.getPackageManager().getNameForUid( 740 Binder.getCallingUid()); 741 742 if (!mCdmaBroadcastRangeManager.disableRange(startMessageId, endMessageId, client)) { 743 log("Failed to remove cdma broadcast subscription for MID range " + startMessageId 744 + " to " + endMessageId + " from client " + client); 745 return false; 746 } 747 748 if (DBG) 749 log("Removed cdma broadcast subscription for MID range " + startMessageId 750 + " to " + endMessageId + " from client " + client); 751 752 setCdmaBroadcastActivation(!mCdmaBroadcastRangeManager.isEmpty()); 753 754 return true; 755 } 756 757 class CellBroadcastRangeManager extends IntRangeManager { 758 private ArrayList<SmsBroadcastConfigInfo> mConfigList = 759 new ArrayList<SmsBroadcastConfigInfo>(); 760 761 /** 762 * Called when the list of enabled ranges has changed. This will be 763 * followed by zero or more calls to {@link #addRange} followed by 764 * a call to {@link #finishUpdate}. 765 */ startUpdate()766 protected void startUpdate() { 767 mConfigList.clear(); 768 } 769 770 /** 771 * Called after {@link #startUpdate} to indicate a range of enabled 772 * values. 773 * @param startId the first id included in the range 774 * @param endId the last id included in the range 775 */ addRange(int startId, int endId, boolean selected)776 protected void addRange(int startId, int endId, boolean selected) { 777 mConfigList.add(new SmsBroadcastConfigInfo(startId, endId, 778 SMS_CB_CODE_SCHEME_MIN, SMS_CB_CODE_SCHEME_MAX, selected)); 779 } 780 781 /** 782 * Called to indicate the end of a range update started by the 783 * previous call to {@link #startUpdate}. 784 * @return true if successful, false otherwise 785 */ finishUpdate()786 protected boolean finishUpdate() { 787 if (mConfigList.isEmpty()) { 788 return true; 789 } else { 790 SmsBroadcastConfigInfo[] configs = 791 mConfigList.toArray(new SmsBroadcastConfigInfo[mConfigList.size()]); 792 return setCellBroadcastConfig(configs); 793 } 794 } 795 } 796 797 class CdmaBroadcastRangeManager extends IntRangeManager { 798 private ArrayList<CdmaSmsBroadcastConfigInfo> mConfigList = 799 new ArrayList<CdmaSmsBroadcastConfigInfo>(); 800 801 /** 802 * Called when the list of enabled ranges has changed. This will be 803 * followed by zero or more calls to {@link #addRange} followed by a 804 * call to {@link #finishUpdate}. 805 */ startUpdate()806 protected void startUpdate() { 807 mConfigList.clear(); 808 } 809 810 /** 811 * Called after {@link #startUpdate} to indicate a range of enabled 812 * values. 813 * @param startId the first id included in the range 814 * @param endId the last id included in the range 815 */ addRange(int startId, int endId, boolean selected)816 protected void addRange(int startId, int endId, boolean selected) { 817 mConfigList.add(new CdmaSmsBroadcastConfigInfo(startId, endId, 818 1, selected)); 819 } 820 821 /** 822 * Called to indicate the end of a range update started by the previous 823 * call to {@link #startUpdate}. 824 * @return true if successful, false otherwise 825 */ finishUpdate()826 protected boolean finishUpdate() { 827 if (mConfigList.isEmpty()) { 828 return true; 829 } else { 830 CdmaSmsBroadcastConfigInfo[] configs = 831 mConfigList.toArray(new CdmaSmsBroadcastConfigInfo[mConfigList.size()]); 832 return setCdmaBroadcastConfig(configs); 833 } 834 } 835 } 836 setCellBroadcastConfig(SmsBroadcastConfigInfo[] configs)837 private boolean setCellBroadcastConfig(SmsBroadcastConfigInfo[] configs) { 838 if (DBG) 839 log("Calling setGsmBroadcastConfig with " + configs.length + " configurations"); 840 841 synchronized (mLock) { 842 Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE); 843 844 mSuccess = false; 845 mPhone.mCi.setGsmBroadcastConfig(configs, response); 846 847 try { 848 mLock.wait(); 849 } catch (InterruptedException e) { 850 log("interrupted while trying to set cell broadcast config"); 851 } 852 } 853 854 return mSuccess; 855 } 856 setCellBroadcastActivation(boolean activate)857 private boolean setCellBroadcastActivation(boolean activate) { 858 if (DBG) 859 log("Calling setCellBroadcastActivation(" + activate + ')'); 860 861 synchronized (mLock) { 862 Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE); 863 864 mSuccess = false; 865 mPhone.mCi.setGsmBroadcastActivation(activate, response); 866 867 try { 868 mLock.wait(); 869 } catch (InterruptedException e) { 870 log("interrupted while trying to set cell broadcast activation"); 871 } 872 } 873 874 return mSuccess; 875 } 876 setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs)877 private boolean setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs) { 878 if (DBG) 879 log("Calling setCdmaBroadcastConfig with " + configs.length + " configurations"); 880 881 synchronized (mLock) { 882 Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE); 883 884 mSuccess = false; 885 mPhone.mCi.setCdmaBroadcastConfig(configs, response); 886 887 try { 888 mLock.wait(); 889 } catch (InterruptedException e) { 890 log("interrupted while trying to set cdma broadcast config"); 891 } 892 } 893 894 return mSuccess; 895 } 896 setCdmaBroadcastActivation(boolean activate)897 private boolean setCdmaBroadcastActivation(boolean activate) { 898 if (DBG) 899 log("Calling setCdmaBroadcastActivation(" + activate + ")"); 900 901 synchronized (mLock) { 902 Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE); 903 904 mSuccess = false; 905 mPhone.mCi.setCdmaBroadcastActivation(activate, response); 906 907 try { 908 mLock.wait(); 909 } catch (InterruptedException e) { 910 log("interrupted while trying to set cdma broadcast activation"); 911 } 912 } 913 914 return mSuccess; 915 } 916 log(String msg)917 protected void log(String msg) { 918 Log.d(LOG_TAG, "[IccSmsInterfaceManager] " + msg); 919 } 920 isImsSmsSupported()921 public boolean isImsSmsSupported() { 922 return mDispatcher.isIms(); 923 } 924 getImsSmsFormat()925 public String getImsSmsFormat() { 926 return mDispatcher.getImsSmsFormat(); 927 } 928 sendStoredText(String callingPkg, Uri messageUri, String scAddress, PendingIntent sentIntent, PendingIntent deliveryIntent)929 public void sendStoredText(String callingPkg, Uri messageUri, String scAddress, 930 PendingIntent sentIntent, PendingIntent deliveryIntent) { 931 mPhone.getContext().enforceCallingPermission(Manifest.permission.SEND_SMS, 932 "Sending SMS message"); 933 if (Rlog.isLoggable("SMS", Log.VERBOSE)) { 934 log("sendStoredText: scAddr=" + scAddress + " messageUri=" + messageUri 935 + " sentIntent=" + sentIntent + " deliveryIntent=" + deliveryIntent); 936 } 937 if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), callingPkg) 938 != AppOpsManager.MODE_ALLOWED) { 939 return; 940 } 941 final ContentResolver resolver = mPhone.getContext().getContentResolver(); 942 if (!isFailedOrDraft(resolver, messageUri)) { 943 Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredText: not FAILED or DRAFT message"); 944 returnUnspecifiedFailure(sentIntent); 945 return; 946 } 947 final String[] textAndAddress = loadTextAndAddress(resolver, messageUri); 948 if (textAndAddress == null) { 949 Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredText: can not load text"); 950 returnUnspecifiedFailure(sentIntent); 951 return; 952 } 953 textAndAddress[1] = filterDestAddress(textAndAddress[1]); 954 mDispatcher.sendText(textAndAddress[1], scAddress, textAndAddress[0], 955 sentIntent, deliveryIntent, messageUri, callingPkg, 956 true /* persistMessageForNonDefaultSmsApp */); 957 } 958 sendStoredMultipartText(String callingPkg, Uri messageUri, String scAddress, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents)959 public void sendStoredMultipartText(String callingPkg, Uri messageUri, String scAddress, 960 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) { 961 mPhone.getContext().enforceCallingPermission(Manifest.permission.SEND_SMS, 962 "Sending SMS message"); 963 if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), callingPkg) 964 != AppOpsManager.MODE_ALLOWED) { 965 return; 966 } 967 final ContentResolver resolver = mPhone.getContext().getContentResolver(); 968 if (!isFailedOrDraft(resolver, messageUri)) { 969 Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: " 970 + "not FAILED or DRAFT message"); 971 returnUnspecifiedFailure(sentIntents); 972 return; 973 } 974 final String[] textAndAddress = loadTextAndAddress(resolver, messageUri); 975 if (textAndAddress == null) { 976 Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: can not load text"); 977 returnUnspecifiedFailure(sentIntents); 978 return; 979 } 980 final ArrayList<String> parts = SmsManager.getDefault().divideMessage(textAndAddress[0]); 981 if (parts == null || parts.size() < 1) { 982 Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: can not divide text"); 983 returnUnspecifiedFailure(sentIntents); 984 return; 985 } 986 987 textAndAddress[1] = filterDestAddress(textAndAddress[1]); 988 989 if (parts.size() > 1 && parts.size() < 10 && !SmsMessage.hasEmsSupport()) { 990 for (int i = 0; i < parts.size(); i++) { 991 // If EMS is not supported, we have to break down EMS into single segment SMS 992 // and add page info " x/y". 993 String singlePart = parts.get(i); 994 if (SmsMessage.shouldAppendPageNumberAsPrefix()) { 995 singlePart = String.valueOf(i + 1) + '/' + parts.size() + ' ' + singlePart; 996 } else { 997 singlePart = singlePart.concat(' ' + String.valueOf(i + 1) + '/' + parts.size()); 998 } 999 1000 PendingIntent singleSentIntent = null; 1001 if (sentIntents != null && sentIntents.size() > i) { 1002 singleSentIntent = sentIntents.get(i); 1003 } 1004 1005 PendingIntent singleDeliveryIntent = null; 1006 if (deliveryIntents != null && deliveryIntents.size() > i) { 1007 singleDeliveryIntent = deliveryIntents.get(i); 1008 } 1009 1010 mDispatcher.sendText(textAndAddress[1], scAddress, singlePart, 1011 singleSentIntent, singleDeliveryIntent, messageUri, callingPkg, 1012 true /* persistMessageForNonDefaultSmsApp */); 1013 } 1014 return; 1015 } 1016 1017 mDispatcher.sendMultipartText( 1018 textAndAddress[1], // destAddress 1019 scAddress, 1020 parts, 1021 (ArrayList<PendingIntent>) sentIntents, 1022 (ArrayList<PendingIntent>) deliveryIntents, 1023 messageUri, 1024 callingPkg, 1025 true /* persistMessageForNonDefaultSmsApp */); 1026 } 1027 isFailedOrDraft(ContentResolver resolver, Uri messageUri)1028 private boolean isFailedOrDraft(ContentResolver resolver, Uri messageUri) { 1029 // Clear the calling identity and query the database using the phone user id 1030 // Otherwise the AppOps check in TelephonyProvider would complain about mismatch 1031 // between the calling uid and the package uid 1032 final long identity = Binder.clearCallingIdentity(); 1033 Cursor cursor = null; 1034 try { 1035 cursor = resolver.query( 1036 messageUri, 1037 new String[]{ Telephony.Sms.TYPE }, 1038 null/*selection*/, 1039 null/*selectionArgs*/, 1040 null/*sortOrder*/); 1041 if (cursor != null && cursor.moveToFirst()) { 1042 final int type = cursor.getInt(0); 1043 return type == Telephony.Sms.MESSAGE_TYPE_DRAFT 1044 || type == Telephony.Sms.MESSAGE_TYPE_FAILED; 1045 } 1046 } catch (SQLiteException e) { 1047 Log.e(LOG_TAG, "[IccSmsInterfaceManager]isFailedOrDraft: query message type failed", e); 1048 } finally { 1049 if (cursor != null) { 1050 cursor.close(); 1051 } 1052 Binder.restoreCallingIdentity(identity); 1053 } 1054 return false; 1055 } 1056 1057 // Return an array including both the SMS text (0) and address (1) loadTextAndAddress(ContentResolver resolver, Uri messageUri)1058 private String[] loadTextAndAddress(ContentResolver resolver, Uri messageUri) { 1059 // Clear the calling identity and query the database using the phone user id 1060 // Otherwise the AppOps check in TelephonyProvider would complain about mismatch 1061 // between the calling uid and the package uid 1062 final long identity = Binder.clearCallingIdentity(); 1063 Cursor cursor = null; 1064 try { 1065 cursor = resolver.query( 1066 messageUri, 1067 new String[]{ 1068 Telephony.Sms.BODY, 1069 Telephony.Sms.ADDRESS 1070 }, 1071 null/*selection*/, 1072 null/*selectionArgs*/, 1073 null/*sortOrder*/); 1074 if (cursor != null && cursor.moveToFirst()) { 1075 return new String[]{ cursor.getString(0), cursor.getString(1) }; 1076 } 1077 } catch (SQLiteException e) { 1078 Log.e(LOG_TAG, "[IccSmsInterfaceManager]loadText: query message text failed", e); 1079 } finally { 1080 if (cursor != null) { 1081 cursor.close(); 1082 } 1083 Binder.restoreCallingIdentity(identity); 1084 } 1085 return null; 1086 } 1087 returnUnspecifiedFailure(PendingIntent pi)1088 private void returnUnspecifiedFailure(PendingIntent pi) { 1089 if (pi != null) { 1090 try { 1091 pi.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE); 1092 } catch (PendingIntent.CanceledException e) { 1093 // ignore 1094 } 1095 } 1096 } 1097 returnUnspecifiedFailure(List<PendingIntent> pis)1098 private void returnUnspecifiedFailure(List<PendingIntent> pis) { 1099 if (pis == null) { 1100 return; 1101 } 1102 for (PendingIntent pi : pis) { 1103 returnUnspecifiedFailure(pi); 1104 } 1105 } 1106 enforceCarrierPrivilege()1107 private void enforceCarrierPrivilege() { 1108 UiccController controller = UiccController.getInstance(); 1109 if (controller == null || controller.getUiccCard(mPhone.getPhoneId()) == null) { 1110 throw new SecurityException("No Carrier Privilege: No UICC"); 1111 } 1112 if (controller.getUiccCard(mPhone.getPhoneId()).getCarrierPrivilegeStatusForCurrentTransaction( 1113 mContext.getPackageManager()) != 1114 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 1115 throw new SecurityException("No Carrier Privilege."); 1116 } 1117 } 1118 1119 /** 1120 * Enforces that the caller has {@link android.Manifest.permission#MODIFY_PHONE_STATE} 1121 * permission or is one of the following apps: 1122 * <ul> 1123 * <li> IMS App 1124 * <li> Carrier App 1125 * </ul> 1126 */ enforcePrivilegedAppPermissions()1127 private void enforcePrivilegedAppPermissions() { 1128 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) 1129 == PackageManager.PERMISSION_GRANTED) { 1130 return; 1131 } 1132 1133 int callingUid = Binder.getCallingUid(); 1134 String carrierImsPackage = CarrierSmsUtils.getCarrierImsPackageForIntent(mContext, mPhone, 1135 new Intent(CarrierMessagingService.SERVICE_INTERFACE)); 1136 try { 1137 if (carrierImsPackage != null 1138 && callingUid == mContext.getPackageManager().getPackageUid( 1139 carrierImsPackage, 0)) { 1140 return; 1141 } 1142 } catch (PackageManager.NameNotFoundException e) { 1143 if (Rlog.isLoggable("SMS", Log.DEBUG)) { 1144 log("Cannot find configured carrier ims package"); 1145 } 1146 } 1147 1148 enforceCarrierPrivilege(); 1149 } 1150 filterDestAddress(String destAddr)1151 private String filterDestAddress(String destAddr) { 1152 String result = null; 1153 result = SmsNumberUtils.filterDestAddr(mPhone, destAddr); 1154 return result != null ? result : destAddr; 1155 } 1156 1157 } 1158